Sql server 使用游标,如何处理SQL中的错误
我有多个数据库,我在其中寻找一个名为“国家”的专栏。如果列存在,则检查列中的空格字符。如果我循环遍历一个游标,没有Countries列的DB将抛出一个错误。我如何处理这个错误 问题:挡块未处理,请帮助我解决问题 查询如下所示Sql server 使用游标,如何处理SQL中的错误,sql-server,tsql,try-catch,database-cursor,Sql Server,Tsql,Try Catch,Database Cursor,我有多个数据库,我在其中寻找一个名为“国家”的专栏。如果列存在,则检查列中的空格字符。如果我循环遍历一个游标,没有Countries列的DB将抛出一个错误。我如何处理这个错误 问题:挡块未处理,请帮助我解决问题 查询如下所示 CREATE PROCEDURE [dbo].[USP_SMSGeneric_CountrySpace] @DB VARCHAR(100) As
CREATE PROCEDURE [dbo].[USP_SMSGeneric_CountrySpace] @DB VARCHAR(100)
As
BEGIN
SET NOCOUNT ON
DECLARE @StudyID varchar(max)
DECLARE @Databasename VARCHAR(max)
DECLARE @QUERY NVARCHAR(MAX)
DECLARE @Protocol varchar(max)
DECLARE @Servername varchar(max)
DECLARE @script VARCHAR(Max)
DECLARE @script1 VARCHAR(Max)
DECLARE @initscript NVARCHAR(Max)
DECLARE @Countries VARCHAR(Max)
DECLARE @Countryrelease VARCHAR(Max)
IF OBJECT_ID('TEMPDB..#OBJMISSING') IS NOT NULL DROP TABLE #OBJMISSING
CREATE TABLE #OBJMISSING (ERRID INT IDENTITY(1,1),ERRNUM BIGINT,ERRMSG VARCHAR(MAX),DBNAME VARCHAR(MAX))
SET @initscript='
DECLARE csrStudy CURSOR FOR
SELECT ProtocolName, DBName, studyid,DBServer AS Servername from SMSAPP.dbo.studymaster WITH (NOLOCK)
WHERE ClientName LIKE ''%NOVARTIS%'' AND studystatus IN (1,2) AND DBServer IN (''SQL002'' ,''SQL004'',''SQL005'')
'
EXEC sp_executesql @initscript
OPEN csrStudy
FETCH NEXT FROM csrStudy INTO @Protocol,@Databasename,@StudyID,@ServerName
WHILE @@FETCH_STATUS = 0
BEGIN
SET @DB = @Servername+'.'+@Databasename
SET @script = '
DECLARE @StrValue VARCHAR(max)
BEGIN TRY
IF EXISTS (
SELECT DISTINCT 1 FROM '+@DB+'.sys.columns c JOIN '+@DB+'.sys.Tables t ON c.Object_ID=t.Object_ID
WHERE c.Name = ''Countries’'' AND t.name =''tblMaterials'')
BEGIN
SELECT @StrValue = ISNULL(@StrValue + '','', '''') + Countries’ FROM (
SELECT DISTINCT (LEN(Countries’ + '','') - LEN(REPLACE(Countries’, '' '', '''') + '',''))CNT,Countries
FROM '+@DB+'.dbo.tblMaterials WITH (NOLOCK) )A WHERE CNT>0
END
END TRY
BEGIN CATCH
INSERT INTO #OBJMISSING VALUES
(ERROR_NUMBER(),ERROR_MESSAGE(),''+@Databasename+'')
END CATCH
IF @StrValue IS NOT NULL -- If any Duplicate values found, then raise an alert
BEGIN
SELECT '+@StudyID+' As StudyID,
''Countries field value Should not have space'' AS Actual ,
''Countries field value exists with space for String :'' + @StrValue AS Discrepancy INTO #tempOutput
我得到以下错误:
链接服务器“SQL001”的OLE DB提供程序“SQLNCLI10”不可用
包含表“RAW.”dbo.“tblMaterials”。该表
不存在或当前用户没有该表的权限
您需要一个
TRY-CATCH
动态SQL外部
显示的错误消息在parse时间,甚至在执行之前(对于该EXEC
语句)。此时,引擎验证表和对象是否存在,如果不存在,则返回错误。执行从未开始,因此它将永远不会到达CATCH
部分。这就是为什么TRY CATCH
需要在动态SQL之外,因为整个动态SQL在解析后将被拒绝
您收到的错误消息来自如下查询:
EXEC('SELECT * FROM [SomeLinkedServer].DatabaseName.SchemaName.NonExistingTable')
Msg 7314,级别16,状态1,第1行OLE DB提供程序“SQLNCLI11”
对于链接服务器,“SomeLinkedServer”不包含表
“数据库名”“SchemaName”“不存在表”“。表不存在或不存在。”
当前用户没有该表的权限
如果您可以将其包装到一个TRY CATCH
,那么控制流将跳转到CATCH,因为错误的严重性足够高:
BEGIN TRY
EXEC('SELECT * FROM [SomeLinkedServer].DatabaseName.SchemaName.NonExistingTable')
END TRY
BEGIN CATCH
SELECT 'This is the catch section'
END CATCH
请注意,在没有动态SQL的情况下,与以下示例的区别:
BEGIN TRY
SELECT 1 FROM [SomeLinkedServer].DatabaseName.SchemaName.NonExistingTable
END TRY
BEGIN CATCH
SELECT 1
END CATCH
Msg 208,16级,状态1,第3行无效对象名称
“DatabaseName.SchemaName.NonExistingTable”
这是因为整个批处理在解析后被拒绝,因此它无法跳转到捕获
,因为它从未开始执行。当使用动态SQL时,动态部分的解析、编译和执行发生在EXEC
点(这正是它是动态的原因),延迟错误抛出以便捕获它
我无法提供完整的修复代码,因为您发布的内容不完整。但如果遵循以下准则,您应该能够忽略错误:
DECLARE @Variable ...
DECLARE MyCursor CURSOR FOR ...
FETCH NEXT FROM MyCursor INTO @Variable
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRY
DECLARE @DynamicSQL VARCHAR(MAX) = ... -- The DynamicSQL may have another TRY CATCH inside
EXEC(@DynamicSQL)
END TRY
BEGIN CATCH
-- Do your catch operation here, you can leave this section empty if you want (not recommended)
END CATCH
FETCH NEXT FROM MyCursor INTO @Variable
END
我建议您首先在动态sql之外使用try-catch“没用,你能描述一下出错时会发生什么吗?非常感谢你的解释,这对我很有用。。。请让我知道在我上面的查询中,我已经创建了带有#objectmissing table的catch块,为什么数据没有插入???@RakeshCS请仔细阅读我的答案,我不知道如何更好地解释它。数据没有插入到catch上的临时表中,因为完整的动态SQL甚至在开始执行之前就被拒绝,并且您的catch在动态SQL中。您好,Ezlo,我是SQL新手,所以我想知道在应该执行错误ocurs else select语句时,如何将错误数据插入catch。U在上面的查询中解释了如何逃逸错误,它将停止执行。如果我不知道哪个数据库有错误,哪个数据库执行了错误,那么逃逸错误就没有用了。。希望你明白我的意思