Оператор PRINT у T-SQL


77

Чому оператор PRINT у T-SQL, здається, працює лише іноді? Які обмежують його використання? Здається, іноді, якщо набір результатів генерується, він стає нульовою функцією, я припускав, щоб запобігти пошкодженню набору результатів, але чи не може результат вийти в іншому наборі результатів, наприклад, підрахунку рядків?


2
Не могли б ви навести приклад коду, який іноді друкується, а іноді ні. Думаю, я не розумію питання.
РБ.

Відповіді:


115

Отже, якщо у вас є щось на зразок наведеного нижче, ви говорите, що не отримаєте результату "друку"?

виберіть * із системних об'єктів
PRINT 'Щойно вибраний * із системних об'єктів'

Якщо ви використовуєте SQL Query Analyzer, ви побачите, що внизу є дві вкладки, одна з яких - "Повідомлення", і саме там відображатимуться оператори "print".
Якщо вас турбує час перегляду операторів друку, ви можете спробувати використати щось на зразок

riseerror ('Моя заява про друк', 10,1) без очікування

Це дасть вам повідомлення негайно, коли буде досягнуто твердження, а не буферизує вихід, як це робить аналізатор запитів за більшості умов.


1
Класна угода. Радий, що це у вас вийшло. Я зазвичай кажу аналізатору запитів, щоб він видав мені текст, щоб я міг бачити повідомлення вбудованими (Ctrl + T). Насолоджуйтесь!
Девід Т. Макнет

1
Які аргументи 10 та 1 у прикладі riserror?
Джон Шнайдер,

10, 1 насправді просто кажуть серверу "тут нічого не бачити". Докладніше про те, що вони насправді означають, див. У документі docs.microsoft.com/en-us/sql/t-sql/language-elements/… .
Девід Т. Макнет

1
При використанні цього способу RaiseErrorідентичний PRINTза винятком часу?
FMFF

1
Я так вважаю, так. Це може мати додаткову перевагу негайного виведення буфера, тому також відображатимуться інші оператори друку, але це те, з чим ви хочете пограти, щоб перевірити. Я розумію, що це викликає негайне виведення черги.
Девід Т. Макнет

38

Оператор Print у TSQL - істота, яку неправильно зрозуміли, ймовірно, через свою назву. Він фактично надсилає повідомлення механізму обробки помилок / повідомлень, який потім передає його до програми, що викликає. PRINT досить німий. Ви можете надіслати лише 8000 символів (4000 символів Unicode). Ви можете надіслати буквальний рядок, змінну рядка (varchar або char) або рядовий вираз. Якщо ви використовуєте RAISERROR, тоді ви обмежитеся лише рядком із 2044 символів. Однак набагато простіше використовувати його для надсилання інформації до програми, що викликає, оскільки вона викликає функцію форматування, подібну до старої printf у стандартній бібліотеці C. RAISERROR може також вказати номер помилки, серйозність та код стану на додаток до текстового повідомлення, а також може використовуватися для повернення визначених користувачем повідомлень, створених за допомогою збереженої процедури системи sp_addmessage.

Ваші процедури обробки помилок не будуть корисними для отримання повідомлень, незважаючи на те, що повідомлення та помилки настільки подібні. Техніка, звичайно, залежить від фактичного способу підключення до бази даних (OLBC, OLEDB тощо). Для того, щоб отримувати та обробляти повідомлення з SQL Server Database Engine, коли ви використовуєте System.Data.SQLClient, вам потрібно створити делегат SqlInfoMessageEventHandler, визначивши метод, який обробляє подію, для прослуховування події InfoMessage для класу SqlConnection. Ви виявите, що інформація про контекст повідомлення, така як серйозність та стан, передається як аргумент зворотного виклику, оскільки з точки зору системи ці повідомлення схожі на помилки.

Це завжди гарна ідея мати спосіб отримати ці повідомлення у своїй програмі, навіть якщо ви просто переглядаєте файл, оскільки вони завжди будуть корисні для них, коли ви намагаєтеся переслідувати справді незрозумілу проблему. Однак я не думаю, що хотів би, щоб кінцеві користувачі коли-небудь їх бачили, якщо ви не можете зарезервувати інформаційний рівень, який відображає матеріали в додатку.


26

Аналізатор запитів буферизує повідомлення. У операторах PRINT і RAISERROR використовується цей буфер, але в інструкції RAISERROR є опція WITH NOWAIT. Щоб негайно надрукувати повідомлення, скористайтесь наступним:

RAISERROR ('Your message', 0, 1) WITH NOWAIT

RAISERROR відображатиме лише 400 символів вашого повідомлення та використовує синтаксис, подібний до функції C printf для форматування тексту.

Зверніть увагу, що використання RAISERROR з опцією WITH NOWAIT призведе до змивання буфера повідомлень, тому буде також виведена вся раніше буферизована інформація.


1
Синтаксис RAISERROR був неприємним завданням, але введення порожнього після мого PRINT зробило свою роботу, дякую за інформацію!
Cobusve

21

Нещодавно я зіткнувся з цим, і в підсумку це сталося тому, що у мене був оператор convert для нульової змінної. Оскільки це спричиняло помилки, увесь оператор print відображався як нульовий, а не друкував взагалі.

Приклад - це не вдасться:

declare @myID int=null
print 'First Statement: ' + convert(varchar(4), @myID)

Приклад - друкується:

declare @myID int=null
print 'Second Statement: ' +  coalesce(Convert(varchar(4), @myID),'@myID is null')

Не просто PRINT: використання оператора + з будь-яким нульовим значенням будь-де в T-SQL призводить до нульового значення, незалежно від того, чи були об’єднані інші речі, які не були нульовими. Використання ISNULL (@myID, '') або COALESCE, як у вас, дозволить null мати змогу об'єднуватися з рядками.
трой

3

На користь того, що хтось, хто читає це запитання, в якому дійсно відсутні висновки друку у своїх вихідних даних, насправді бувають випадки, коли друк виконується, але не повертається клієнту. Я не можу сказати вам конкретно, якими вони є. Я можу сказати вам, що якщо поставити оператор go безпосередньо перед будь-яким оператором друку та після нього, ви побачите його, якщо він буде виконаний.


Я також стикався з випадками, коли оператор друку робить запис у вікно повідомлення, коли очікувалося. Це трапляється зі мною після фіксації або відкоту.
Кріс Сімпсон,

Додавання GOвисловлювань злило моє PRINTs з оболонки, що я і шукав
Метт Кемп,

0

Чи є у вас змінні, пов'язані з цими операторами друку, були виведені? якщо так, я виявив, що якщо змінна не має значення, тоді оператор print не буде виведений.


Ви здаєтесь, що не розумієте ефекту об’єднання NULLза допомогою рядка. PRINT 'a' + CAST(NULL AS VARCHAR(MAX));поводиться точно так, як я очікував.
binki
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.