Sql server 在SQLServer2005中使用xml时,为什么必须启用ARITHABORT?

Sql server 在SQLServer2005中使用xml时,为什么必须启用ARITHABORT?,sql-server,xml,Sql Server,Xml,在SQLServer2005中使用xml时,为什么必须启用ARITHABORT? 我试着研究为什么我必须设置这个,但找不到一个答案告诉我为什么。只是它需要设置 以下是我在第行取出设置的ARITHABORT时收到的具体错误消息: 参数错误:无法分析插入列表-插入失败 因为以下设置选项的设置不正确: “阿里沙波特”。验证集合选项是否正确,以便与索引一起使用 计算列和/或查询通知上的视图和/或索引 和/或xml数据类型方法 我的存储过程在一个环境中使用odbc从asp.net调用时运行良好。然后,当我

在SQLServer2005中使用xml时,为什么必须启用ARITHABORT? 我试着研究为什么我必须设置这个,但找不到一个答案告诉我为什么。只是它需要设置

以下是我在第行取出设置的ARITHABORT时收到的具体错误消息:

参数错误:无法分析插入列表-插入失败 因为以下设置选项的设置不正确: “阿里沙波特”。验证集合选项是否正确,以便与索引一起使用 计算列和/或查询通知上的视图和/或索引 和/或xml数据类型方法

我的存储过程在一个环境中使用odbc从asp.net调用时运行良好。然后,当我将它移动到另一个存储过程时,我必须在存储过程的开头添加SET ARITHABORT ON。我将在下面介绍存储过程的相关部分。以及调用它的代码

CREATE PROCEDURE [dbo].[myproc]
   @ruserid             varchar(8),
   @folder_list         xml,
   @insert_list         xml
AS

SET NOCOUNT ON
SET ARITHABORT ON

DECLARE @rindex integer
DECLARE @errormsg nvarchar(4000)
DECLARE @folder_cnt integer
DECLARE @insert_cnt integer


SET @rindex = -1

-- temp table to hold inserts
CREATE TABLE #insert_list (rowidx integer IDENTITY(1,1), insertdesc varchar(96) COLLATE database_default, insertfolder integer)

-- temp table to hold folders
CREATE TABLE #folder_list (rowidx integer IDENTITY(1,1), folderdesc varchar(144) COLLATE database_default, insertfolder integer)

-- insert inserts to make sure data is compatible in type
BEGIN TRY
   INSERT INTO #insert_list (insertdesc, insertfolder)
   SELECT insert_list.listitem.value('@insertdesc', 'varchar(96)'), insert_list.listitem.value('@insertfolder', 'integer')
   FROM @insert_list.nodes('/Root/Insert') AS insert_list(listitem)
END TRY
BEGIN CATCH
   SET @errormsg = N'PARAMETER ERROR: INSERT LIST COULD NOT BE PARSED - ' + ERROR_MESSAGE()
   RAISERROR(@errormsg, 16, 1)
   RETURN
END CATCH

-- insert folders to make sure data is compatible in type
BEGIN TRY
   INSERT INTO #folder_list (insertfolder, folderdesc)
   SELECT folder_list.listitem.value('@insertfolder', 'integer'), folder_list.listitem.value('@folderdesc', 'varchar(144)')
   FROM @folder_list.nodes('/Root/Folder') AS folder_list(listitem)
END TRY
BEGIN CATCH
   SET @errormsg = N'PARAMETER ERROR: FOLDER LIST COULD NOT BE PARSED - ' + ERROR_MESSAGE()
   RAISERROR(@errormsg, 16, 1)
   RETURN
END CATCH

-- insert rows
BEGIN TRANSACTION

BEGIN TRY

INSERT INTO my_folder_request (ruserid)
VALUES ( @ruserid )

SET @rindex = SCOPE_IDENTITY()

INSERT INTO my_insert_request (rindex, insertdesc, insertfolder)
SELECT @rindex, #insert_list.insertdesc, #insert_list.insertfolder
FROM #insert_list
ORDER BY #insert_list.rowidx

INSERT INTO my_folder_desc (rindex, insertfolder, folderdesc)
SELECT @rindex, #folder_list.insertfolder, #folder_list.folderdesc
FROM #folder_list
ORDER BY #folder_list.rowidx

END TRY
BEGIN CATCH
   IF @@TRANCOUNT > 0
      ROLLBACK TRANSACTION
   SET @errormsg = N'DATA INSERTION FAILED WITH MESSAGE - ' + ERROR_MESSAGE()
   RAISERROR(@errormsg, 16, 1)
   RETURN
END CATCH

IF @@TRANCOUNT > 0
   COMMIT TRANSACTION

-- return result
SELECT @rindex AS rindex

DROP TABLE #insert_list
DROP TABLE #folder_list

GO           
呼叫码

  ' build odbc command for inserting creation request
  intRequestIndex = 0
  cmdAddRequest = New System.Data.Odbc.OdbcCommand
  cmdAddRequest.CommandType = CommandType.StoredProcedure
  cmdAddRequest.CommandTimeout = 60
  cmdAddRequest.CommandText = "{CALL myproc ( ?, ?, ?)}"

  ' add parameters to odbc command
  cmdAddRequest.Parameters.Add("@ruserid", OdbcType.VarChar, 8).Value = SafeODBCParamString(m_strUID)
  cmdAddRequest.Parameters.Add("@folder_list", OdbcType.NText).Value = System.Text.Encoding.Unicode.GetString(strmFolderList.ToArray())
  cmdAddRequest.Parameters.Add("@insert_list", OdbcType.NText).Value = System.Text.Encoding.Unicode.GetString(strmInsertList.ToArray())

  ' run odbc command returning info about results
  cmdAddRequest.Connection = Me.ODBCConnection()
  Try
     rdrRequestData = cmdAddRequest.ExecuteReader(CommandBehavior.CloseConnection) 

除非您正在创建XML索引,否则不需要将ARITHABORT设置为ON。也就是说,我知道在使用ADO.NET时会出现一些性能问题(我相信它会将ARITHABORT设置为OFF)。打开它并没有什么坏处,因为当查询执行过程中出现溢出或被零除错误时,它会终止查询。

我认为在线丛书中的这句话是一种提示:“在计算列或索引视图上创建或更改索引时,必须启用SET-ArithPort。“因此,nodes方法必须在内部创建索引视图或其他内容。但这只是一个有根据的猜测。

我发现了一个解决ARITHABORT问题的解决方案,该解决方案是从.Net客户端使用xml输入参数调用存储过程

using (var conn = new SqlConnection(dbConnectionString))  
{  
    SqlCommand command = new SqlCommand("[stored procedure name here]", conn);  
    command.CommandType = CommandType.StoredProcedure;  
    command.Parameters.AddWithValue("@parameter_name", parameter_xml_value);  

    conn.Open();  

    SqlCommand arithabortCommand = new SqlCommand("SET ARITHABORT ON", conn);  
    arithabortCommand.ExecuteNonQuery();  

    command.ExecuteNonQuery();  
    conn.Close();  
} // using (var conn = new SqlConnection(dbConnectionString))  
根据此线程(在底部),它可能取决于您的兼容性级别:

 80: Error
100: Okay

威尔·里卡兹和约翰·吉尔默的答案是可靠的。他们回答了“为什么”和“什么时候”。我将对约翰的回答作进一步的阐述:

我刚刚经历了同样的问题,并想知道为什么ARITHABORT设置很重要——特别是因为我在其他几个服务器上运行的是相同的软件,没有问题。使用两台不同的服务器,我执行了以下操作:

SET ARITHABORT OFF
DECLARE @message XML
SELECT @message = (SELECT '1' As Bar FOR XML PATH('Foo'), TYPE)
SELECT @@Version, @@Options, compatibility_level from sys.databases where name='xxxx'
SELECT @message.exist('/Foo/Bar') -- This line fails on only one server
两台服务器之间的区别在于数据库兼容性级别:

 80: Error
100: Okay

为了解决这个问题,我将数据库的反兼容性级别从2000年更改为2005年,它可以正常工作。

您不能在存储过程中明确说明正确的选项吗在集合上设置ANSI\U NULL在集合上设置ANSI\U填充在集合上设置ANSI\U在集合上设置ARITHABORT警告在集合上设置CONCAT\U NULL在集合上设置NULL在集合数字上设置中止在集合上设置带引号的\U标识符在'