1

我正在运行以下查询:

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 事务包围,以保持过程安全可靠(以防任何步骤失败)。有人可以帮忙吗?提前致谢。

4

2 回答 2

2

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

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

您的脚本还有许多其他问题。因为表名以数字开头,所以不符合常规标识符命名规则,必须用方括号或双引号括起来。传递给的文字参数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;
于 2018-03-15T11:30:38.123 回答
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不会让您丢失表内容,它只会更改表引用名称并更新它的所有约束和索引引用。如果要重命名的表不存在,它也会引发错误。也许您想要的是将您的流程包装在事务中并在出现故障时回滚。

编辑:

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

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您知道一切正常后使用 a(从那时起,其他用户将看到更改和修改将被保留)。如果出现故障(您需要TRY/CATCH阻止来处理错误),您可以发出 aROLLBACK来恢复您的更改。

于 2018-03-15T10:57:56.413 回答