【问题标题】:Individual T-SQL statements run fine individually but not when combined单独的 T-SQL 语句单独运行良好,但组合时不能
【发布时间】:2016-03-15 11:32:15
【问题描述】:

我有一堆要执行的 SQL 语句来更新数据库的架构 - 它们都单独运行良好(即当我一个接一个地手动运行它们时)但是当我尝试组合时遇到问题将它们整合到一个脚本中,并包含一些版本控制逻辑。

我的脚本如下:

DECLARE @VersionCode varchar(20)
DECLARE @Description varchar(50)
DECLARE @Author varchar(20)
DECLARE @AppVersion varchar (10)

SET @VersionCode = 'version code';
SET @Description = 'description';
SET @Author = 'author';
SET @AppVersion = 'app version';

BEGIN
    IF NOT EXISTS (SELECT * FROM [Version] WHERE [VersionCode] = @VersionCode)
    BEGIN
        ALTER TABLE [Journal] ADD [BreakDurationNew] INT NULL
        UPDATE [Journal] SET BreakDurationNew = BreakDuration
        ALTER TABLE [Journal] DROP COLUMN [BreakDuration]
        EXEC sp_rename 'Journal.BreakDurationNew', 'BreakDuration', 'COLUMN';

        -- create triggers on JournalBreak so that BreakDuration on Journal is updated
        CREATE TRIGGER TR_JournalBreak_Insert ON [JournalBreak]
        FOR INSERT
        AS  
        BEGIN
            UPDATE [Journal] SET BreakDuration = (coalesce([dbo].[CalculateJournalBreak]([JournalId]),(0))) WHERE [JournalId] IN (SELECT JournalId FROM INSERTED) 
        END

        CREATE TRIGGER TR_JournalBreak_Update ON [JournalBreak]
        FOR UPDATE
        AS  
        BEGIN
            UPDATE [Journal] SET BreakDuration = (coalesce([dbo].[CalculateJournalBreak]([JournalId]),(0))) WHERE [JournalId] IN (SELECT JournalId FROM INSERTED)
            UPDATE [Journal] SET BreakDuration = (coalesce([dbo].[CalculateJournalBreak]([JournalId]),(0))) WHERE [JournalId] IN (SELECT JournalId FROM DELETED)
        END

        -- insert version record
        INSERT INTO [RG].[dbo].[Version] (VersionCode, Description, Author, AppVersion) VALUES
        (@VersionCode, @Description, @Author, @AppVersion)
    END
END

我的猜测是我的脚本有一些(或一堆东西!)语法错误,但我目前无法发现它。有人可以帮忙吗?

干杯!

【问题讨论】:

  • 您还没有对 T-SQL 的“感觉”。例如,CREATE TRIGGER 必须是批处理中的第一个命令(或前面有 GO)。因此,您不能有条件地创建触发器,除非您使用动态 SQL。
  • @GordonLinoff 太真实了!在研究这个时,我确实看到了关于 CREATE TRIGGER 的东西 - 即使我删除了两个 CREATE TRIGGER 语句,它也会因为一些无害的东西而失败......
  • “它因一些无害的东西而失败......” > 失败的原因是什么?
  • @TT。回复晚了非常抱歉。我得到的错误是'Invalid column name 'BreakDurationNew'UPDATE [Journal] SET BreakDurationNew = BreakDuration 行上,这几乎表明它完全忽略了它之前的行(在其中添加了新列)
  • 将其全部包装在单独的动态 SQL 语句中。

标签: sql-server tsql


【解决方案1】:

试试@GordonLinoff 评论

DECLARE @VersionCode VARCHAR(20) = 'version code'
DECLARE @Description VARCHAR(50) = 'description'
DECLARE @Author VARCHAR(20) = 'author'
DECLARE @AppVersion VARCHAR(10) = 'app version'
DECLARE @CMD NVARCHAR(Max) = ''

BEGIN
    IF NOT EXISTS (
            SELECT *
            FROM [Version]
            WHERE [VersionCode] = @VersionCode
            )
    BEGIN
        SET @CMD = 'ALTER TABLE [Journal] ADD [BreakDurationNew] INT NULL'
    EXEC SP_EXECUTESQL @CMD

    SET @CMD = 'UPDATE [Journal] SET BreakDurationNew = BreakDuration

    ALTER TABLE [Journal] DROP COLUMN [BreakDuration]'

    EXEC SP_EXECUTESQL @CMD

    EXEC sp_rename 'Journal.BreakDurationNew','BreakDuration','COLUMN';

    -- create triggers on JournalBreak so that BreakDuration on Journal is updated
    SET @CMD = '
    CREATE TRIGGER TR_JournalBreak_Insert ON [JournalBreak]
    FOR INSERT
    AS  
    BEGIN
        UPDATE [Journal] SET BreakDuration = (coalesce([dbo].[CalculateJournalBreak]([JournalId]),(0))) WHERE [JournalId] IN (SELECT JournalId FROM INSERTED) 
    END'

    EXEC SP_EXECUTESQL @CMD

    SET @CMD = '
    CREATE TRIGGER TR_JournalBreak_Update ON [JournalBreak]
    FOR UPDATE
    AS  
    BEGIN
        UPDATE [Journal] SET BreakDuration = (coalesce([dbo].[CalculateJournalBreak]([JournalId]),(0))) WHERE [JournalId] IN (SELECT JournalId FROM INSERTED)
        UPDATE [Journal] SET BreakDuration = (coalesce([dbo].[CalculateJournalBreak]([JournalId]),(0))) WHERE [JournalId] IN (SELECT JournalId FROM DELETED)
    END
    '

    EXEC SP_EXECUTESQL @CMD

    -- insert version record
    INSERT INTO [RG].[dbo].[Version] (VersionCode, Description, Author, AppVersion) VALUES
    (@VersionCode, @Description, @Author, @AppVersion)
END
END

【讨论】:

  • 感谢您的回答。但是,它仍然不适合我。我得到的错误是'Invalid column name 'BreakDurationNew'UPDATE [Journal] SET BreakDurationNew = BreakDuration 行上,这几乎表明它完全忽略了它之前的行(在其中添加了新列)-类似于我简单地删除CREATE TRIGGER 命令时
【解决方案2】:

看起来您正在尝试发明某种补丁机制。我建议制作单独的脚本:

  1. 一些脚本将检查您在特定服务器上的版本,并决定是否运行真正的补丁脚本

  2. 简单的“愚蠢”补丁脚本,所有 DDL 和 DML 语句(需要时带有 GO 分隔符)适用于确定的版本

所以我的建议是开发一个流控制工具,给它一个功能来确定服务器上的版本和另一个功能 - 将适当的补丁脚本发送到sqlcmd.exe。如果有错误,可能会检查错误。这甚至可以是一个批处理文件 (*.cmd)。

【讨论】:

    猜你喜欢
    • 2011-03-02
    • 1970-01-01
    • 2019-01-30
    • 1970-01-01
    • 2018-07-26
    • 2018-02-09
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多