2009-07-08 21 views
13

¿Por qué tengo que CONFIGURAR ARITHABORT cuando uso xml en sql server 2005? Intenté investigar por qué tengo que configurar esto, pero no pude encontrar una respuesta que me dijera por qué. Solo que necesita ser configurado.¿Por qué tengo que CONFIGURAR ARITHABORT cuando uso xml en sql server 2005?

Aquí es el mensaje de error específico que consigo cuando saco la ARITHABORT SET on line:

PARAMETER ERROR: INSERT LIST COULD NOT BE PARSED - INSERT failed because the following SET options have incorrect settings: 'ARITHABORT'. Verify that SET options are correct for use with indexed views and/or indexes on computed columns and/or query notifications and/or xml data type methods.

Mi procedimiento almacenado llamado trabajó bien desde asp.net utilizando ODBC en un entorno. Luego, cuando lo moví a otro, tuve que agregar SET ARITHABORT ON al comienzo del procedimiento almacenado. Incluyo las secciones relevantes del procedimiento almacenado a continuación. Y el código que lo está llamando.

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   

Llamar código

' 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) 

Respuesta

6

Creo que este enunciado de los libros en línea lo insinúa: "SET ARITHABORT debe estar activado cuando se crean o cambian índices en columnas calculadas o vistas indizadas". Por lo tanto, el método de nodos debe crear una vista indexada internamente o algo así. Pero esto es solo una suposición educada.

0

menos que esté creando índices XML que no es necesario establecer ARITHABORT en ON. Dicho esto, sé que hay algunos problemas de rendimiento cuando utilizo ADO.NET (que creo que desactiva ARITHABORT). No hace daño tenerlo activado porque terminará una consulta cuando se produce un error de desbordamiento o de división por cero durante la consulta. ejecución.

4

Aquí hay una solución que encontré al problema ARITHABORT al llamar a un procedimiento almacenado con un parámetro de entrada xml de un cliente .Net.

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)) 
+0

No se pudo establecer explícitamente que sólo las opciones correctas en el ¿proc almacenado? 'SET ANSI_NULLS EN ANSI_PADDING SET EN ANSI_WARNINGS SET en ARITHABORT SET en CONCAT_NULL_YIELDS_NULL SET EN SET NUMERIC_ROUNDABORT OFF activar quoted_identifier' –

2

Will Rickards' y John Gilmer de las respuestas son sólidos. Respondieron el 'por qué' y 'cuándo'. Ampliaré un poco la respuesta de John:

Acabo de experimentar este mismo problema y me pregunté por qué importaba la configuración de ARITHABORT, especialmente porque tengo un software idéntico ejecutándose sin problemas en varios otros servidores. El uso de dos servidores diferentes, que ejecuta la siguiente:

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 

Resulta que la diferencia entre los dos servidores es el nivel de compatibilidad de base de datos:

80: Error 
100: Okay 
Cuestiones relacionadas