Ответ 1
Yup.. CALL
- это конструктор/синтаксис, используемый из драйвера ODBC, как указывает ваша документация.
В документации T-SQL нет ссылки на CALL
, только EXEC
.
Это не работает, потому что это не T-SQL.
Рассмотрим:
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.
Язык T-SQL не распознает escape-последовательности ODBC; EXEC
- единственная команда, доступная для вызова хранимой процедуры. Управляющие последовательности ODBC интерпретируются библиотеками на стороне клиента (например, ODBC, OLE DB, ADO, ADO.NET) и транслируются на реальный синтаксис T-SQL на лету перед выполнением.
Конечный результат: вы можете вызвать свою хранимую процедуру верхнего уровня у клиента, используя CALL
, если хотите, но если эта процедура вызывает других, она должна использовать EXEC
.
Тот же принцип применяется для последовательных escape-последовательностей даты/времени.
Я столкнулся с проблемой (при миграции баз данных), что MSSQL будет принимать инструкцию CALL
в хранимой процедуре - SQL Management Studio жалуется, но сам запрос выполняется успешно.
Итак, такой оператор выполняет:
create procedure spwho
as begin
call sp_who2
end
go
exec spwho
К сожалению, несмотря на то, что процедура создана, она не дает никаких результатов (но также она не вызывает никаких ошибок или предупреждений).
Итак, в таких случаях оператор CALL
не будет вызывать ошибки в MSSQL, но в любом случае никогда не должен использоваться, так как он не работает.