如何检查sp_rename是否成功完成?

时间:2018-03-15 10:49:58

标签: sql-server tsql sp-rename

我正在运行以下查询:

SELECT * INTO dbo.2015_10_2_cs FROM dbo.2015_10_2

IF NOT EXISTS 
(SELECT type FROM sys.indexes WHERE object_id = object_id('dbo.2015_10_2_cs') 
AND NAME ='cci' AND type = 5)
BEGIN
    CREATE CLUSTERED COLUMNSTORE INDEX cci
    ON dbo.2015_10_2_cs
    DROP TABLE dbo.2015_10_2
    EXEC sp_rename "dbo.2015_10_2_cs" , "dbo.2015_10_2"
END

我想确保将表dbo.2015_10_2_cs重命名为dbo.2015_10_2的部分成功完成(不丢失任何数据)。 循环中的步骤应该用SQL事务包围,以保持进程安全可靠(如果任何步骤失败)。 任何人都可以帮忙吗?提前谢谢。

2 个答案:

答案 0 :(得分:2)

  

EXEC sp_rename" dbo.2015_10_2_cs" ," dbo.2015_10_2"

这不符合您的期望。如果在新表名中指定模式名称,则新表将命名为[dbo]。[dbo.2015_10_2]。重命名的表隐含在现有表的模式中,因为必须使用ALTER SCHEMA而不是sp_rename来在模式之间移动对象。

您的脚本还有许多其他问题。因为表名以数字开头,所以它不符合regular identifier naming rules,必须用方括号或双引号括起来。传递给sp_rename的文字参数应该是单引号。您还可以检查存储过程返回代码以确定成功或失败。下面的示例在具有结构化错误处理的事务中执行这些任务。

DECLARE @rc int;
BEGIN TRY
    BEGIN TRAN;
    IF NOT EXISTS 
        (SELECT type FROM sys.indexes WHERE object_id = object_id(N'dbo.2015_10_2_cs') 
        AND NAME ='cci' AND type = 5)
    BEGIN
        CREATE CLUSTERED COLUMNSTORE INDEX cci
        ON dbo.[2015_10_2_cs];
        DROP TABLE dbo.[2015_10_2];
        EXEC @rc = sp_rename 'dbo.[2015_10_2_cs]' , '2015_10_2';
        IF @rc <> 0
        BEGIN
            RAISERROR('sp_rename returned return code %d',16,1);
        END;
    END;
    COMMIT;
END TRY
BEGIN CATCH
    IF @@TRANCOUNT > 0 ROLLBACK;
    THROW;
END CATCH;

答案 1 :(得分:1)

您可以使用EXISTS检查表名和架构。

IF NOT EXISTS (SELECT 'table does not exist' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'2015_10_2'AND TABLE_SCHEMA = 'dbo')
BEGIN

    RAISERROR('The table doesn''t exist!!!!', 16, 1)

END

sp_rename不会让您丢失表内容,它只会更改表引用名称并更新其所有的约束和索引引用。如果要重命名的表不存在,它也会引发错误。也许你想要的是将你的进程包装在一个事务中,如果出现故障就回滚。

修改

对于基本事务处理,您可以使用以下内容。请阅读documentation使用交易,可能需要一段时间才能知道它是如何正常工作的。

IF OBJECT_ID('tempdb..#Test') IS NOT NULL
    DROP TABLE #Test

CREATE TABLE #Test (Number INT)

SELECT AmountRecords = COUNT(1) FROM #Test -- AmountRecords = 0

BEGIN TRY

    BEGIN TRANSACTION

    -- Do your statements here

    INSERT INTO #Test (Number)
    VALUES (1)

    DECLARE @errorVariable INT = CONVERT(INT, 'NotAnInteger!!') -- Example of error: can't convert

    COMMIT

END TRY

BEGIN CATCH -- If something goes wrong

    IF @@TRANCOUNT > 0 -- ... and transaction is still open
        ROLLBACK -- Revert statements from the BEGIN TRANSACTION onwards

END CATCH


SELECT AmountRecords = COUNT(1) FROM #Test -- AmountRecords = 0 (the transaction was rolled back and the INSERT reverted)

基本上,您使用BEGIN TRANSACTION启动还原点,以便在出现故障时返回。一旦您知道一切正常,就使用COMMIT(从那时起,其他用户将看到更改和修改将被保留)。如果某些内容失败(您需要TRY/CATCH阻止来处理错误),您可以发出ROLLBACK来还原您的更改。