1

我有一个正确执行的存储过程。现在,我尝试添加TRY CATCHT-SQL 语句。

添加后

BEGIN TRY

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
SET XACT_ABORT ON
GO

/****** add new column Accountid  to Metainformation table ******/

IF NOT EXISTS (SELECT * FROM SYSCOLUMNS WHERE NAME = 'Accountid' AND ID = OBJECT_ID('[GSF].[dbo].[Metainformation]'))
BEGIN
    ALTER TABLE [GSF].[dbo].[Metainformation] ADD Accountid int 
END
GO



IF EXISTS (SELECT * FROM SYSCOLUMNS WHERE NAME = 'Accountid' AND ID = OBJECT_ID('[GSF].[dbo].[Metainformation]'))
BEGIN
    UPDATE [GSF].[dbo].[Metainformation]  
    SET MP.Accountid = AD.Accountid
    FROM [GSF].[dbo].[Metainformation] MI, [GSF].[dbo].[AccountDetails] AD
    WHERE MI.DetailID= AD.DetailID
END
GO

我的GO语句出现错误,在 GO 附近显示错误说语法不正确。

任何指针或替代使用?

更新代码:

USE GSF
GO

/****** add new column AccountId  to MetaInformation table ******/
IF NOT EXISTS (SELECT * FROM **SYS.COLUMNS** WHERE NAME = 'AccountId' AND ID = OBJECT_ID('[GSF].[dbo].[MetaInformation]'))
    ALTER TABLE [GSF].[dbo].[MetaInformation] ADD AccountId uniqueidentifier 

BEGIN TRANSACTION;
BEGIN TRY


SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON


/****** If the column AccountId exists, Update all the AccountId values in MetaInformation from AccountDetails ******/

IF EXISTS (SELECT * FROM **SYS.COLUMNS** WHERE NAME = 'AccountId' AND ID = OBJECT_ID('[GSF].[dbo].[MetaInformation]'))
BEGIN
    UPDATE MP  
    SET MP.AccountId = AD.AccountId
    FROM [GSF].[dbo].[MetaInformation] MP
    **INNER JOIN**  
    [GSF].[dbo].[AccountDetails] AD
    ON MP.AllocationDetailId = AD.AllocationDetailId
END

/****** Drop AccountId column from AccountDetails ******/

IF EXISTS (SELECT * FROM SYS.COLUMNS WHERE NAME = 'AccountId' AND ID = OBJECT_ID('[GSF].[dbo].[AccountDetails]'))
    ALTER TABLE [GSF].[dbo].[AccountDetails] DROP COLUMN AccountId 


/****** add two new PStage values to [PStageToCategory] table ******/

INSERT INTO [GSF].[dbo].[PStageToCategory]
   (PStage, PStageToCategoryName)
   VALUES(19,1)

INSERT INTO [GSF].[dbo].[PStageToCategory]
   (PStage, PStageToCategoryName)
   VALUES(21,1)



/****** Drop and create new ViewName view to remove reference of AccountId ******/

USE GSF

IF EXISTS ( SELECT * FROM sys.views WHERE name = 'ViewName')
DROP VIEW ViewName


DECLARE @sql_view NVARCHAR(MAX);
SET @sql_view = '<VIEW DEFINITION>';
EXEC sp_executesql @sql_view;

COMMIT TRANSACTION
END TRY

BEGIN CATCH
SELECT
    ERROR_NUMBER() AS ErrorNumber
   ,ERROR_SEVERITY() AS ErrorSeverity
   ,ERROR_STATE() AS ErrorState
   ,ERROR_PROCEDURE() AS ErrorProcedure
   ,ERROR_LINE() AS ErrorLine
   ,ERROR_MESSAGE() AS ErrorMessage;
END CATCH

我正在使用这个脚本来更改生产中的架构。所以,我包括 try catch 只是为了知道错误和事务,如果在运行中脚本中有错误(只有一个它将运行),则回滚。你觉得有道理吗?

另外,我根据您的评论对我的脚本进行了更改。你怎么看 ?

4

3 回答 3

3

“GO 不是 Transact-SQL 语句;它是 sqlcmd 和 osql 实用程序以及 SQL Server Management Studio 代码编辑器识别的命令”——引用自MSDN

下面的示例代码假定您只是从 SSMS 或其他实用程序之一执行脚本。

以下是对代码的一些改进。

1 - TRY/CATCH 代码块需要在一批中。因此,GO需要在block之后。

2 - SYSCOLUMNS 表已折旧,最终将从产品中删除。请参阅 Jason Strate关于此主题的博客文章。

3 - 如果 IF 表达式后面有一个语句,则不需要 BEGIN/END 代码块。

4 - 您应该避免使用 ANSI 92 连接,因为它们在 SQL Server 2012 中不起作用。请参阅 Mike Walsh关于此主题的博客文章。

5 - 使用 MP.Accountid 代替 MI.Accountid 时出现错字。

6 - 在语句的末尾使用分号,因为有人认为这是将来的要求。

总之,当我编写存储过程并希望将错误代码返回给调用应用程序时,我会使用 TRY/CATCH 块。此示例代码仅返回有关错误的信息。

真挚地

约翰

-- 
-- Use correct database and set session settings
--

-- Switch to correct database
USE [GSF];
GO

-- Change session settings
SET ANSI_NULLS ON;
SET QUOTED_IDENTIFIER ON;
SET XACT_ABORT ON;
GO


--
-- My code block
--

BEGIN TRY

-- Add column if it does not exist
IF NOT EXISTS (SELECT * FROM SYS.COLUMNS AS C WHERE C.NAME = 'Accountid' AND C.OBJECT_ID = OBJECT_ID('dbo.Metainformation'))
    ALTER TABLE [dbo].[Metainformation] ADD Accountid INT;

-- Update the column regardless
IF EXISTS (SELECT * FROM FROM SYS.COLUMNS AS C WHERE C.NAME = 'Accountid' AND C.OBJECT_ID = OBJECT_ID('dbo.Metainformation'))
    UPDATE Metainformation
    SET Accountid = AD.Accountid
    FROM [dbo].[Metainformation] AS MI JOIN [dbo].[AccountDetails] AS AD ON MI.DetailID = AD.DetailID;

END TRY


--
-- My error handling
--

-- Error Handler
BEGIN CATCH
    SELECT
        ERROR_NUMBER() AS ErrorNumber
       ,ERROR_SEVERITY() AS ErrorSeverity
       ,ERROR_STATE() AS ErrorState
       ,ERROR_PROCEDURE() AS ErrorProcedure
       ,ERROR_LINE() AS ErrorLine
       ,ERROR_MESSAGE() AS ErrorMessage;
END CATCH

GO
于 2013-09-04T15:09:32.553 回答
0

只要确保您的GO_. 任何空格都会改变关键字GO。所以就在每一个之后GO,做ENTER

于 2013-09-04T06:58:08.097 回答
0

看过您的代码后,我建议您根本不要使用TRY...CATCH

TRY...CATCH 构造不能跨越多个批次[ 1 ]。TRY...CATCH 构造不能跨越多个 Transact-SQL 语句块。例如,TRY…CATCH 构造不能跨越 Transact-SQL 语句的两个 BEGIN…END 块,也不能跨越 IF…ELSE 构造。

1批次作为单独的命令发送到 SQL Server。客户端工具需要知道如何将一个长脚本分成多个批次发送到服务器。按照惯例,大多数客户端工具(Management Studio、OSQL 等)使用GO

GO 不是 Transact-SQL 语句;

于 2013-09-04T07:21:39.000 回答