Вопрос:
Рассмотрим:
CREATE PROCEDURE LowerCityDiscounts @city VARCHAR(45), @decrease DECIMAL(10,2) AS BEGIN BEGIN TRANSACTION; UPDATE Customers SET discnt = discnt — @decrease WHERE Customers.city = @city; UPDATE Customers SET discnt = 0 WHERE Customers.city = @city AND discnt < 0 COMMIT; END;
Я попытался вызвать эту процедуру с помощью:
CALL LowerCityDiscounts ‘Cleveland’, 5;
но это вызывает только
Msg 102, Level 15, State 1, Line 1 Incorrect syntax near ‘Cleveland’.
Тем не менее, если я изменяю вещи на
EXEC LowerCityDiscounts ‘Cleveland’, 5;
все работает нормально. Это несмотря на то, что документация, в которой указано, что call является правильным синтаксисом.
Почему EXEC работает, когда call не работает?
Лучший ответ:
Yup.. CALL – это конструктор/синтаксис, используемый из драйвера ODBC, как указывает ваша документация.
В документации T-SQL нет ссылки на CALL, только EXEC.
Это не работает, потому что это не T-SQL.
Ответ №1
Язык T-SQL не распознает escape-последовательности ODBC; EXEC – единственная команда, доступная для вызова хранимой процедуры. Управляющие последовательности ODBC интерпретируются библиотеками на стороне клиента (например, ODBC, OLE DB, ADO, ADO.NET) и транслируются на реальный синтаксис T-SQL на лету перед выполнением.
Конечный результат: вы можете вызвать свою хранимую процедуру верхнего уровня у клиента, используя CALL, если хотите, но если эта процедура вызывает других, она должна использовать EXEC.
Тот же принцип применяется для последовательных escape-последовательностей даты/времени.
Ответ №2
Я столкнулся с проблемой (при миграции баз данных), что MSSQL будет принимать инструкцию CALL в хранимой процедуре – SQL Management Studio жалуется, но сам запрос выполняется успешно.
Итак, такой оператор выполняет:
create procedure spwho as begin call sp_who2 end go exec spwho
К сожалению, несмотря на то, что процедура создана, она не дает никаких результатов (но также она не вызывает никаких ошибок или предупреждений).
Итак, в таких случаях оператор CALL не будет вызывать ошибки в MSSQL, но в любом случае никогда не должен использоваться, так как он не работает.