Sql server 单个T-SQL语句单独运行良好,但在组合时运行不好

Sql server 单个T-SQL语句单独运行良好,但在组合时运行不好,sql-server,tsql,Sql Server,Tsql,我有一堆SQL语句,我想执行它们来更新数据库的模式-它们都可以单独运行(即,当我一个接一个地手动运行它们时),但是当我试图将它们组合到一个脚本中,并围绕一些版本控制逻辑时,我遇到了问题 我的脚本如下: DECLARE @VersionCode varchar(20) DECLARE @Description varchar(50) DECLARE @Author varchar(20) DECLARE @AppVersion varchar (10) SET @VersionCode = 'v

我有一堆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
我的猜测是我的脚本在语法上有一些错误(或一大堆错误!),但我目前无法发现。有人能帮忙吗


干杯

试试看@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

尝试一下@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

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

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

  • 包含所有DDL和DML语句(需要时使用GO分隔符)的简单“愚蠢”修补程序脚本,适用于确定的版本


  • 因此,我的建议是开发一个流控制工具,为它提供一个功能来确定服务器上的版本,并提供另一个功能-将适当的补丁脚本发送到
    sqlcmd.exe
    。并可能检查是否有错误。这甚至可能是一个批处理文件(*.cmd)。

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

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

  • 包含所有DDL和DML语句(需要时使用GO分隔符)的简单“愚蠢”修补程序脚本,适用于确定的版本


  • 因此,我的建议是开发一个流控制工具,为它提供一个功能来确定服务器上的版本,并提供另一个功能-将适当的补丁脚本发送到
    sqlcmd.exe
    。并可能检查是否有错误。这甚至可能是一个批处理文件(*.cmd)。

    您对t-SQL还没有“感觉”<例如,代码>创建触发器,需要是批处理中的第一个命令(或前面有
    GO
    )。因此,除非使用动态SQL,否则不能有条件地创建触发器。@GordonLinoff太正确了!在研究这个问题时,我确实看到了CREATE TRIGGER的东西——即使我删除了两个CREATE TRIGGER语句,它也会因一些无害的东西而失败……“它因一些无害的东西而失败…”如何失败?@TT。很抱歉反应太晚。我得到的错误是在
    UPDATE[Journal]SET BreakDurationNew=BreakDuration
    行上的
    无效列名'BreakDurationNew'
    ,这几乎表明它完全忽略了它前面的行(在其中添加了新列),将其全部包装在单独的动态SQL语句中。您还没有对t-SQL的“感觉”<例如,代码>创建触发器,需要是批处理中的第一个命令(或前面有
    GO
    )。因此,除非使用动态SQL,否则不能有条件地创建触发器。@GordonLinoff太正确了!在研究这个问题时,我确实看到了CREATE TRIGGER的东西——即使我删除了两个CREATE TRIGGER语句,它也会因一些无害的东西而失败……“它因一些无害的东西而失败…”如何失败?@TT。很抱歉反应太晚。我得到的错误是在
    UPDATE[Journal]SET BreakDurationNew=BreakDuration
    行上的
    无效列名'BreakDurationNew'
    ,这几乎表明它完全忽略了它前面的行(在其中添加了新列),将其全部打包到单独的动态SQL语句中。感谢您的回答。然而,它对我仍然不起作用。我得到的错误是,
    更新[Journal]SET BreakDurationNew=BreakDuration
    行上的
    无效列名'BreakDurationNew'
    ,这几乎表明它完全忽略了它前面的行(这会在中添加新列)-类似于我简单地删除
    CREATE TRIGGER
    commandsThanks以获取答案时的情况。然而,它对我仍然不起作用。我得到的错误是
    更新[Journal]SET BreakDurationNew=BreakDuration
    行上的
    无效列名'BreakDurationNew'
    ,这几乎表明它完全忽略了它前面的行(在中添加了新列)-类似于我只是删除
    创建触发器
    命令时的错误