SQL Server 2005 / XML存储过程-Unicode到ASCII? (异常0xc00ce508)
时间:2020-03-06 14:35:00 来源:igfitidea点击:
我这里有一个MSSQL2005存储过程,该过程应该将XML消息作为输入,并将其内容存储到表中。
表字段是varchars,因为我们的delphi后端应用程序无法处理unicode。
现在,传入的消息已被编码为ISO-8859-1. 直到包括> 128个标准字符集在内的所有字符(在本例中为????,这是芬兰语的组成部分)之前,一切都很好。这将导致DB服务器引发异常0xc00ce508.
数据库的默认排序规则以及表和字段的默认排序规则设置为latin1,该值应与ISO-8859-1相同。
XML消息使用XML子系统进行解析,如下所示:
ALTER PROCEDURE [dbo].[parse] @XmlIn NVARCHAR(1000) AS SET NOCOUNT ON DECLARE @XmlDocumentHandle INT DECLARE @XmlDocument VARCHAR(1000) BEGIN SET @XmlDocument = @XmlIn EXECUTE sp_xml_preparedocument @XmlDocumentHandle OUTPUT, @XmlDocument BEGIN TRANSACTION //the xml message's fields are looped through here, and rows added or modified in two tables accordingly // like ... DECLARE TempCursor CURSOR FOR SELECT AM_WORK_ID,CUSTNO,STYPE,REFE,VIN_NUMBER,REG_NO,VEHICLE_CONNO,READY_FOR_INVOICE,IS_SP,SMANID,INVOICENO,SUB_STATUS,TOTAL,TOTAL0,VAT,WRKORDNO FROM OPENXML (@XmlDocumentHandle, '/ORDER_NEW_CP_REQ/ORDER_NEW_CUSTOMER_REQ',8) WITH (AM_WORK_ID int '@EXIDNO',CUSTNO int '@CUSTNO',STYPE VARCHAR(1) '@STYPE',REFE VARCHAR(50) '@REFE',VIN_NUMBER VARCHAR(30) '@VEHICLE_VINNO', REG_NO VARCHAR(20) '@VEHICLE_LICNO',VEHICLE_CONNO VARCHAR(30) '@VEHICLE_CONNO',READY_FOR_INVOICE INT '@READY_FOR_INVOICE',IS_SP INT '@IS_SP', SMANID INT '@SMANID',INVOICENO INT '@INVOICENO',SUB_STATUS VARCHAR(1) '@SUB_STATUS',TOTAL NUMERIC(12,2) '@TOTAL',TOTAL0 NUMERIC(12,2) '@TOTAL0',VAT NUMERIC(12,2) '@VAT',WRKORDNO INT '@WRKORDNO') OPEN TempCursor FETCH NEXT FROM TempCursor INTO @wAmWork,@wCustNo,@wType,@wRefe,@wVIN,@wReg,@wConNo,@wRdy,@wIsSp,@wSMan,@wInvoNo,@wSubStatus,@wTot,@wTot0,@wVat,@wWrkOrdNo // ... etc COMMIT TRANSACTION EXECUTE sp_xml_removedocument @XmlDocumentHandle END
以前,存储过程曾经使用nvarchar进行输入,但是由于这导致了古老的后端应用程序(Delphi 5 + ODBC)出现问题,因此我们不得不将字段切换为varchars,此时一切都中断了。
我还尝试了使用nvarchar并在开始时将其转换为varchar,但是结果是相同的。
解决方案
我们提到的错误代码似乎来自MSXML库。那是如何参与的?根据问题,我假设我们将varchar参数传递给存储过程,然后使用该参数插入或者更新varchar列。
但是,这与异常代码不匹配,因此它必须在实际存储过程之外发生,否则我们将在存储过程中基于xml进行其他操作。
请检查并相应地修改问题。
我将回答我自己的问题,因为我设法解决的不仅仅是神秘的问题...
1)存储过程必须反映正确的代码页以进行转换:
@XmlIn NVARCHAR(2000) @XmlDocument VARCHAR(2000) SELECT @XmlDocument = @XmlIn COLLATE SQL_Latin1_General_CP1_CI_AS
2)XML输入必须指定相同的字符集:
<?xml version="1.0" encoding="ISO-8859-1" ?>
我不知道是否有足够的权限来编辑答案的人会看到这个,但是当答案正确时,我想补充一点,在没有明确指定排序规则的情况下,在这种情况下将使用数据库的默认排序规则,因为它隐式分配给每个无排序规则的varchar变量。
所以
DECLARE @XmlDocument VARCHAR(2000) COLLATE SQL_Latin1_General_CP1_CI_AS
也应该做到这一点。