Ошибка неверного идентификатора SQL - PullRequest
1 голос
/ 09 марта 2012

У меня есть функция, которая выполняет оператор выбора. Когда я пытаюсь выполнить этот оператор выбора, который возвращает единственное значение и устанавливает его в переменную, моя функция падает со следующей ошибкой:

Сообщение 203, Уровень 16, Состояние 2, Процедура Info_GetWholeNumber, Строка 20
Имя «ВЫБЕРИТЕ МАКС» (ЛЕН (CAST (FLOOR ([pcom_audit_cant_con])) AS VARCHAR (38)))) AS WHOLE_NO FROM Auditorias.prod_com_audit 'не является действительный идентификатор.

Если я копирую и вставляю это выражение select, оно работает нормально ... поэтому это не select, это как-то связано с моим EXEC ... в любом случае вот мой код функций ...

ALTER FUNCTION [dbo].[Info_GetWholeNumber]
(
    @TABLE VARCHAR(MAX)
    , @COLUMN VARCHAR(MAX)
)
RETURNS INT
AS
BEGIN
    -- Declare the return variable here
    DECLARE @WHOLE_NO INT

    -- Add the T-SQL statements to compute the return value here
    DECLARE @SQL VARCHAR(MAX)
    SET @SQL = 'SELECT MAX(LEN(CAST(FLOOR([' + @COLUMN + ']) AS VARCHAR(38))))
      AS WHOLE_NO FROM ' + @TABLE
    EXEC @WHOLE_NO = @SQL

    -- Return the result of the function
    RETURN @WHOLE_NO

END

Если у кого-нибудь есть идеи, как я могу это исправить, я буду очень признателен за помощь! Заранее спасибо!

ОБНОВЛЕНИЕ:

ОК, поэтому я пытаюсь использовать функцию sp_executesql, как указано, и я собираюсь вставить новую функцию.

ALTER FUNCTION [dbo].[Info_GetWholeNumber]
(
@TABLE VARCHAR(MAX)
, @COLUMN VARCHAR(MAX)
)
RETURNS INT
AS
BEGIN
DECLARE @WHOLE_NO INT
DECLARE @SQL NVARCHAR(MAX)
DECLARE @PARAMS NVARCHAR(MAX)

SET @SQL = N'SELECT @WHOLE_NOOUT = MAX(LEN(CAST(FLOOR(@COL) AS VARCHAR(38)))) FROM @TBL'
SET @PARAMS = N'@COL VARCHAR(MAX), @TBL VARCHAR(MAX), @WHOLE_NOOUT INT OUTPUT'

EXECUTE sp_executesql @SQL, @PARAMS, @COL = @COLUMN, @TBL = @TABLE, @WHOLE_NOOUT = @WHOLE_NO OUTPUT;

-- Return the result of the function
RETURN @WHOLE_NO

END

Теперь я получаю эту ошибку:

Сообщение 1087, Уровень 16, Состояние 1, Строка 1 Необходимо объявить табличную переменную "@TBL"

Что, на мой взгляд, кажется правильным, поскольку переменные не объявлены иначе, как в переменной @PARAM ... Я что-то здесь упускаю?

Ответы [ 2 ]

4 голосов
/ 09 марта 2012

Вы не можете ни назначать напрямую из оператора EXEC, ни напрямую назначать переменную из динамического SQL EXEC d (это выходит за рамки).Это также не должно вызываться из функции, так как SQL ожидает, что функции будут детерминированными, а на самом деле это не так (на самом деле, даже если вы исправите свою ошибку, она все равно, вероятно, не будет работать).

Предполагается, чтовы меняете способ вызова этого кода, вам нужно знать, как получить значение из динамического sql.Если вы хотите передать переменную из динамической строки SQL, вы должны использовать EXEC SP_ExecuteSQL с выходным параметром.

Вот простой пример:

DECLARE @whole_no int;
DECLARE @SQL nvarchar(500);
DECLARE @Parms nvarchar(500);;

SET @SQL = N'SELECT @whole_noOUT = 1';
SET @Parms = N'@whole_noOUT int OUTPUT';

EXECUTE sp_executesql @SQL, @Parms, @whole_noOUT=@whole_no OUTPUT;
SELECT @WHOLE_NO;

В этом примере мы устанавливаем определение параметра и выходной параметр.В общем, sp_executesql является предпочтительным методом для вызова динамического sql, так как он может быть параметризован, что одновременно повышает безопасность, избегая необходимости конкатенации sql напрямую, но также позволяет повторное использование плана, когда ваш sql полностью параметризован.

Я также должен добавить обязательное предупреждение о том, что вам действительно не следует создавать динамический sql таким каверзным способом, как вы открываете себя для внедрения SQL, ни сейчас, ни в будущем.Я понимаю, что вы не можете параметризовать свой конкретный запрос, но, по крайней мере, вы должны использовать QUOTENAME() в имени столбца вместо жесткого кодирования [].

Подробнее о sp_executesql здесь: http://msdn.microsoft.com/en-us/library/ms188001.aspx И еще на QUOTENAME() здесь: http://msdn.microsoft.com/en-us/library/ms176114.aspx

0 голосов
/ 09 марта 2012

Ламак правильный.Вы не можете выполнить хранимую процедуру (или что-либо, способное обновлять, вставлять, удалять) внутри функции.

Функции предназначены только для чтения.

Возможно, вы захотите рассмотреть возможность использованияхранимая процедура вместо вашей функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...