Рассмотрим следующую хранимую процедуру:
CREATE OR ALTER PROCEDURE MySchema.MyProcedure
@myDateTimeParam DATETIME = GETDATE()
AS
BEGIN
-- Do something spectacular
END
При вызове объявление параметра завершается ошибкой «Ошибка преобразования типа данных nvarchar на дату». Это можно обойти, изменив код следующим образом:
CREATE OR ALTER PROCEDURE MySchema.MyProcedure
@myDateTimeParam DATETIME = NULL
AS
BEGIN
IF @myDateTimeParam IS NULL
SET @myDateTimeParam = GETDATE();
-- Do something spectacular
END
Однако предположим, что @myDateTimeParam
не имеет значения по умолчанию:
CREATE OR ALTER PROCEDURE MySchema.MyProcedure
@myDateTimeParam DATETIME
AS
BEGIN
-- Do something spectacular
END
В этом случае вы не можете просто передать GETDATE()
в качестве формального параметра следующим образом:
EXEC MySchema.MyProcedure GETDATE()
поскольку это также приводит к ужасной ошибке «Ошибка преобразования типа данных nvarchar в дату». Единственный обходной путь - сначала объявить переменную, а затем передать ее:
DECLARE @myDateTimeParam DATETIME = GETDATE();
EXEC MySchema.MyProcedure @myDateTimeParam;
Почему это? И исходный, и целевой типы данных - DATETIME
. Теоретически ошибка преобразования типа данных не должна возникать при использовании результата GETDATE()
в качестве значения параметра по умолчанию или значения формального параметра.
Есть какая-то техническая причина, по которой это не работает? В документации MSDN нет ничего, что указывало бы на то, что это не должно работать.
«потому что вы не можете», к сожалению, является наиболее убедительной причиной того, почему вы не можете использовать вызов функции там, где ожидается параметр, см. stackoverflow.com/questions/2399104/…
для меня это звучит как "потому что это не очень хорошо" - это ответ
@Cato, выражающий неприязнь к SQL Server, бесполезен для OP.
@Larnu - Я не сказал, что мне не нравится SQL-сервер, я говорю, что эта его часть выглядит плохо спроектированной и просто немного дрянной. Он спрашивает «почему». Мне кажется, что авторы синтаксического анализатора не удосужились реализовать возможность предоставления функции в качестве параметра, тогда как языки, подобные VB.net, продумали это, вы можете отправить результат вызова функции даже на ссылочный параметр. .
.. Кроме того, важно управлять ожиданиями людей от продукта. Мы не «фан-клуб SQL», мы должны упомянуть любые функции «ниже номинальной». Я не работаю в Microsoft, никому не продаю.
Сказать, что продукт не очень хорош, - значит выразить неприязнь. Если бы вы сказали: «MySQL не очень хорош» или «Python не очень хорош», я бы сделал тот же комментарий.
Это описано в документации СОЗДАТЬ ПРОЦЕДУРУ (Transact-SQL) в подзаголовке дефолт в разделе аргументы:
A default value for a parameter. If a default value is defined for a parameter, the procedure can be executed without specifying a value for that parameter. The default value must be a constant or it can be NULL. The constant value can be in the form of a wildcard, making it possible to use the LIKE keyword when passing the parameter into the procedure.
Акцент мой.
GETDATE()
не является константой, поэтому не может использоваться в качестве значения DEFAULT
. Следовательно, почему вам нужно использовать формат ниже, поскольку тогда значение GETDATE()
определяется во время выполнения:
CREATE PROC YourProc @Param date = NULL
AS
IF @Param IS NULL BEGIN
SET @Param = GETDATE();
END;
...
Спасибо. Это проясняет одну часть вопроса. Теперь мне просто нужно разобраться, что происходит с EXECUTE
. :)
Только что нашел в документации EXECUTE
: «Если вы передадите одно слово, которое не начинается с @ и не заключено в кавычки, например, если вы забыли @ в имени параметра - слово обрабатывается как строка nvarchar, несмотря на отсутствие кавычек». Думаю, это объясняет.
Правильно, @MikeHofer. Итак, если бы вы сделали что-то вроде EXEC YourProc GETDATE;
, это было бы интерпретировано как EXEC YourProc N'GETDATE'
;. Добавление скобок превращает его во что-то вроде EXEC YourProc N'GETDATE'();
, что не имеет смысла для компилятора.
А @Cato? Что это даже в отношении?
если я отправлю GETDate () в его сохраненную процедуру в качестве параметра, я получу другое сообщение об ошибке. Похоже, текст не обрабатывается как varchar
Учитывая, что параметр в SP OP - datetime
, @Cato, вы получите сообщение об ошибке. буквальная строка'GETdate()'
не может быть преобразован в datetime
.
это GETdate () в моих кавычках, как при цитировании того, что было отправлено, а не в фактическом тексте кода.
На какую версию SQL Server вы ориентируетесь?
CREATE OR ALTER
был добавлен совсем недавно. В любом случае значения по умолчанию должны быть постоянными. Это четко задокументировано в СОЗДАТЬ ПРОЦЕДУРУ