T-SQL -- 为什么 ALTER 和 UPDATE 语句只在分离到它们自己的批处理中时才运行?

Joh*_*rne 0 t-sql database sql-server alter-table sql-update

我有 update 和 alter 语句,它们仅在将它们放入自己的批处理中时才运行。下面是我的精简版。

DROP TABLE #tmpImportData
USE database_name
GO

DECLARE @localVar VARCHAR(MAX) = 'data'
DECLARE @localVar VARCHAR(MAX) = 'data'
DECLARE @localVar VARCHAR(MAX) = 'data'
DECLARE @localVar int = 1
--Etc...

DECLARE @localVar INT
DECLARE @localVarVARCHAR(50)    
DECLARE @localVar AS BINARY (16)    
---Etc...


CREATE TABLE #tmpImportData (GuideFirstName VARCHAR(MAX), GuideLastName VARCHAR(MAX), 
                             email VARCHAR(MAX), group_id_text VARCHAR(MAX), CandidateName VARCHAR(MAX), 
                             grade_text VARCHAR(5), dateofbirth DATETIME

                             )

SET @sql = 'BULK INSERT #tmpImportData FROM '''+@fileName+''' WITH (FIELDTERMINATOR ='';'', ROWTERMINATOR = ''\n'', FIRSTROW = 1)'
EXEC (@sql)

--John O. How many rows from the import
SELECT @countCandidateImport = count(*) FROM #tmpImportData

--Fix some import data before any proccessing. We need to remove any punctuation, extra spaces, etc.
UPDATE #tmpImportData SET CandidateName = LTRIM(RTRIM(CandidateName)) FROM #tmpImportData
UPDATE #tmpImportData SET CandidateName = Replace(CandidateName,'.', '') FROM #tmpImportData
--UPDATE #tmpImportData SET CandidateName = Replace(CandidateName,',', '') FROM #tmpImportData

--Check DB for current district. If not exists create new one
SELECT @districtId = id, @ditrict_admins_restricted = CountAdminPermited, @candidates_restricted = count_candidate_restricted
FROM DistrictsTable WHERE name = RTRIM(LTRIM(@districtName))


--John O. What is whytry?
IF @districtId IS NULL
BEGIN
    INSERT INTO districtstable (name, active, CountAdminPermited, why_try_permitted) VALUES (RTRIM(LTRIM(@districtName)), 1, 3, @iswhyTry)
    SELECT @districtId = SCOPE_IDENTITY()
END
ELSE BEGIN
    SELECT @count_created_district_admins = count(*) 
    FROM GuidesTable gt
    INNER JOIN guides_to_permission gtp ON gtp.guide_id = gt.ID
    WHERE gt.DistrictID = @districtId AND gtp.permission_id = 0 AND gt.Active = 1

    IF(@count_created_district_admins >= @ditrict_admins_restricted)
    BEGIN
        SET @messageID = 1
    END

    SELECT @count_created_candidates = count(*)
    FROM CandidatesTable ct
    WHERE ct.DistrictID =  @districtId AND ct.Active = 1
    IF @count_created_candidates + @countCandidateImport >= @candidates_restricted
    BEGIN
        SET @messageID = 2  
    END

    IF(@messageID <> -1)
        RETURN
END
select 1
--Create School
DECLARE @schoolId AS INT
SET @schoolId = NULL
SELECT @schoolId = SchoolsTable.ID FROM SchoolsTable WHERE SchoolsTable.Name = LTRIM(RTRIM(@schoolName))
IF @schoolId IS NULL
    BEGIN
        INSERT INTO schoolstable (districtid, name, Active) VALUES (@districtId, @schoolName, 1)
        SELECT @schoolId = SCOPE_IDENTITY()
    END
ELSE 

SET @adminGuideId = NULL
SELECT @adminGuideId = GuidesTable.ID FROM GuidesTable WHERE LTRIM(RTRIM(FirstName)) = LTRIM(RTRIM(@FirstName)) 
    AND LTRIM(RTRIM(LastName)) = LTRIM(RTRIM(@LastName)) AND LTRIM(RTRIM(EmailAddress)) = LTRIM(RTRIM(@adminLogin))
select @adminGuideId
IF @adminGuideId IS NULL 
BEGIN
        SET @password = HASHBYTES('MD5', @passwordAdmin)                

        INSERT INTO GuidesTable (DistrictID, ClassID, FirstName         , LastName          , EmailAddress, [Password], createddate, Administrator, Active, website_access_level_id)
        VALUES                  (@districtId, 0     , @FirstName        , @LastName         , @adminLogin , @password , GetDate()  , 1            , 1     , 1)
        SET @tmpGuideId = SCOPE_IDENTITY()
        INSERT INTO guides_to_permission (guides_to_permission.guide_id ,guides_to_permission.permission_id) 
        VALUES                           (@tmpGuideId                   ,0                 )
        INSERT INTO guides_to_school_access (guides_to_school_access.guide_id , guides_to_school_access.school_id) 
        VALUES                              (@tmpGuideId                      , @schoolId                        )
END
ELSE BEGIN
        SELECT @AccessToSchoolId = gtsa.id FROM guides_to_school_access gtsa WHERE @adminGuideId = gtsa.guide_id AND @schoolId = gtsa.school_id
        IF @AccessToSchoolId IS NULL
        BEGIN
            INSERT INTO guides_to_school_access (guides_to_school_access.guide_id , guides_to_school_access.school_id) 
            VALUES                              (@adminGuideId                    , @schoolId                        )
        END
END
GO
--Create unique guides
--declare @SQL1 nvarchar(max)
--set @SQL1 = '
ALTER TABLE #tmpImportData ADD group_id INT
ALTER TABLE #tmpImportData ADD guide_id INT
ALTER TABLE #tmpImportData ADD password_plain_text VARCHAR(500)
ALTER TABLE #tmpImportData ADD guide_email VARCHAR(500)
ALTER TABLE #tmpImportData ADD class_id INT 

--exec sp_executesql @SQL1      
GO

UPDATE #tmpImportData SET group_id = CAST(group_id_text AS INT)
UPDATE #tmpImportData SET group_id = 0 WHERE group_id IS NULL

SELECT * FROM #tmpImportData
GO
Run Code Online (Sandbox Code Playgroud)

因此,该表可以使用上面的代码进行更新和更改。但是如果我删除了最后一个之前的两个 Go 语句,并且只在 select 之后保留最后一个。该表未更新或更改。知道为什么会这样吗?

另外,如果我用 NO GO 语句运行它,除了改变、更新和选择之外,一切都会被执行。

ror*_*.ap 5

因为您无法执行添加列的 DDL 查询,然后在同一批次中执行使用该列的 DML 查询。

这是一篇更详细地回答这个问题的帖子,即使它来自一个与你的问题相反的问题:

https://social.msdn.microsoft.com/Forums/sqlserver/en-US/66198247-dc69-4a74-a853-13e4408611e7/why-am-i-able-to-execute-ddl-and-dml-in-同批次?论坛=transactsql

具体来说:

SQL 在执行之前编译批处理。(批处理是 GO 命令之间的一切)。编译时,如果命令引用表中存在的列,则该列在编译时必须存在。

由于您的ALTER语句(即 DDL 语句)将该列添加group_id到 中#tmpImportData,因此该列不能用于您的UPDATE语句中的同一批。