Почему нельзя использовать GETDATE () в качестве значения по умолчанию для параметра процедуры или значения в инструкции EXECUTE?

Рассмотрим следующую хранимую процедуру:

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 нет ничего, что указывало бы на то, что это не должно работать.

На какую версию SQL Server вы ориентируетесь? CREATE OR ALTER был добавлен совсем недавно. В любом случае значения по умолчанию должны быть постоянными. Это четко задокументировано в СОЗДАТЬ ПРОЦЕДУРУ

Panagiotis Kanavos 18.12.2018 13:27

«потому что вы не можете», к сожалению, является наиболее убедительной причиной того, почему вы не можете использовать вызов функции там, где ожидается параметр, см. stackoverflow.com/questions/2399104/…

Alex K. 18.12.2018 13:27

для меня это звучит как "потому что это не очень хорошо" - это ответ

Cato 18.12.2018 14:32

@Cato, выражающий неприязнь к SQL Server, бесполезен для OP.

Larnu 18.12.2018 14:45

@Larnu - Я не сказал, что мне не нравится SQL-сервер, я говорю, что эта его часть выглядит плохо спроектированной и просто немного дрянной. Он спрашивает «почему». Мне кажется, что авторы синтаксического анализатора не удосужились реализовать возможность предоставления функции в качестве параметра, тогда как языки, подобные VB.net, продумали это, вы можете отправить результат вызова функции даже на ссылочный параметр. .

Cato 18.12.2018 15:50

.. Кроме того, важно управлять ожиданиями людей от продукта. Мы не «фан-клуб SQL», мы должны упомянуть любые функции «ниже номинальной». Я не работаю в Microsoft, никому не продаю.

Cato 18.12.2018 16:06

Сказать, что продукт не очень хорош, - значит выразить неприязнь. Если бы вы сказали: «MySQL не очень хорош» или «Python не очень хорош», я бы сделал тот же комментарий.

Larnu 18.12.2018 16:08
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
7
2 639
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это описано в документации СОЗДАТЬ ПРОЦЕДУРУ (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. :)

Mike Hofer 18.12.2018 13:28

Только что нашел в документации EXECUTE: «Если вы передадите одно слово, которое не начинается с @ и не заключено в кавычки, например, если вы забыли @ в имени параметра - слово обрабатывается как строка nvarchar, несмотря на отсутствие кавычек». Думаю, это объясняет.

Mike Hofer 18.12.2018 13:32

Правильно, @MikeHofer. Итак, если бы вы сделали что-то вроде EXEC YourProc GETDATE;, это было бы интерпретировано как EXEC YourProc N'GETDATE' ;. Добавление скобок превращает его во что-то вроде EXEC YourProc N'GETDATE'();, что не имеет смысла для компилятора.

Larnu 18.12.2018 13:38

А @Cato? Что это даже в отношении?

Larnu 18.12.2018 14:44

если я отправлю GETDate () в его сохраненную процедуру в качестве параметра, я получу другое сообщение об ошибке. Похоже, текст не обрабатывается как varchar

Cato 18.12.2018 15:51

Учитывая, что параметр в SP OP - datetime, @Cato, вы получите сообщение об ошибке. буквальная строка'GETdate()' не может быть преобразован в datetime.

Larnu 18.12.2018 16:06

это GETdate () в моих кавычках, как при цитировании того, что было отправлено, а не в фактическом тексте кода.

Cato 18.12.2018 16:08

Другие вопросы по теме