SQL Сервер: хранимая процедура не работает, но работает вне хранимой процедуры - PullRequest
0 голосов
/ 14 марта 2020

SQL Сервер: следующая хранимая процедура не работает, но оператор SQL работает вне хранимой процедуры.

CREATE PROCEDURE schema1.dropConstraints
      (@schemaName AS nvarchar, @tableName AS nvarchar) 
AS
BEGIN
    DECLARE @cname nvarchar(80)
    DECLARE @sqlStatement nvarchar(100)

    DECLARE myCursor CURSOR LOCAL FOR
        SELECT constraint_name 
        FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
        WHERE constraint_schema = @schemaName 
          AND table_name = @tableName;

    OPEN myCursor;
    FETCH NEXT FROM myCursor INTO @cname;

    WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @sqlStatement = 'ALTER TABLE ' + @schemaName + '.' + @tableName + ' DROP CONSTRAINT ' + @cname;
        EXEC sp_executesql @sqlStatement;

        FETCH NEXT FROM myCursor INTO @cname;
    END;

    CLOSE myCursor;
    DEALLOCATE myCursor;
END;

Вызов хранимой процедуры

exec schema1.dropConstraints 'schema1', 'Foo';

Таблица Ограничения Foo (PK, FK) не были удалены. Нет ошибок.

Но если запустить код вне хранимой процедуры, он работает нормально.

    DECLARE @schemaName nvarchar(80) = 'schema1';
    DECLARE @tableName nvarchar(80) = 'Foo';

    DECLARE @cname nvarchar(80)
    DECLARE @sqlStatement nvarchar(100)

    DECLARE myCursor CURSOR LOCAL FOR 
        SELECT constraint_name 
        FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
        WHERE constraint_schema = @schemaName AND table_name = @tableName;

    OPEN myCursor;
    FETCH NEXT FROM myCursor INTO @cname;

    WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @sqlStatement = 'ALTER TABLE ' + @schemaName + '.' + @tableName + ' DROP CONSTRAINT ' + @cname;
        EXEC sp_executesql @sqlStatement;

        FETCH NEXT FROM myCursor INTO @cname;
    END;

    CLOSE myCursor;
    DEALLOCATE myCursor;

Это работает. Ограничения таблицы Foo (PK, FK) были удалены. В чем разница?

логин: sa.

1 Ответ

2 голосов
/ 14 марта 2020

Максимальная длина символов отсутствует в этих объявлениях типов данных параметров:

CREATE PROCEDURE schema1.dropConstraints
      (@schemaName AS nvarchar, @tableName AS nvarchar) 

Поскольку длина по умолчанию равна 1, предоставленные значения молча усекаются до одного символа, и результаты не соответствуют ожидаемым.

Хорошей практикой является обеспечение того, чтобы типы и длины данных параметров соответствовали столбцам, на которые есть ссылки. В случае представлений INFORMATION_SCHEMA обратитесь к документации , и вы найдете соответствующий тип данных nvarchar (128). Лично мне нравится использовать sysname для типов идентификаторов в SQL Server, что является синонимом для nvarchar(128).

CREATE PROCEDURE schema1.dropConstraints
      @schemaName AS sysname, @tableName AS sysname
...