2017-09-06 591 views
1

VB.Net Windows窗体程序在“生产”环境中正常运行(即.EXE在Windows 2008R2服务器上运行,连接到SQL Server 2008数据库在另一台服务器上)。ODBC SQL Server驱动程序 - “44444”错误附近的语法错误 - 关于recordset.UpdateBatch方法

该平台与“测试”环境(即在AWS上托管;由管理向AWS的管理的系统管理员的数据库服务器升级到SQL Server 2016)一起被克隆。

问题:AWS测试中的这个错误是否指向某种类型的SQL 2016配置问题?

代码段如下:

Dim cn As New ADODB.Connection() 
cn.ConnectionString = BuildConnectStringODBC() 
cn.Open() 
rs = New Recordset 
rs.CursorLocation = ADODB.CursorLocationEnum.adUseClient 
rs.CursorType = ADODB.CursorTypeEnum.adOpenKeyset 
rs.LockType = ADODB.LockTypeEnum.adLockBatchOptimistic 
rs.Open("ImportTempTable", cn) 
rs.AddNew() 
rs.Fields("StateCD").Value = CRMortgage.StateCD 
rs.Fields("CountyCD").Value = CRMortgage.CountyCD     
' etc. 
rs.UpdateBatch() 

单步调试示出了所有的对RS上述方法正确的目标工作直到rs.UpdateBatch其失败,出现“不正确的语法”错误。

这个程序在“生产”和系统管理员中多次执行没有问题,我怀疑SQL Server配置或选项有些问题,但我们不确定哪里可以启动。

编辑更新:

下面是ImportTempTable从SQL管理Studio中的脚本架构:

CREATE TABLE [dbo].[ImportTempTable](
    [StateCD] [varchar](2) NULL, 
    [CountyCD] [varchar](3) NULL, 
    [SaleMnYear] [datetime] NULL, 
    [LenderName] [varchar](40) NULL, 
    [MDSID] [varchar](6) NULL, 
    [Amt_PUR] [int] NULL, 
    [Nbr_MTG] [int] NULL, 
    [Amt_MTG] [int] NULL, 
    [Nbr_JUMBO] [int] NULL, 
    [Amt_JUMBO] [int] NULL, 
    [Nbr_GOVT] [int] NULL, 
    [Amt_GOVT] [int] NULL, 
    [Nbr_Fixed] [int] NULL, 
    [Nbr_ARMS] [int] NULL, 
    [Nbr_NewConst] [int] NULL, 
    [Amt_Fixed] [int] NULL, 
    [Amt_ARMS] [int] NULL, 
    [Amt_NewConst] [int] NULL, 
    [LTV] [real] NULL, 
    [Nbr_Below80] [int] NULL, 
    [Nbr_80_85] [int] NULL, 
    [Nbr_85_90] [int] NULL, 
    [Nbr_Above90] [int] NULL, 
    [LoanType] [varchar](1) NULL, 
    [SaleType] [varchar](1) NULL, 
    [RateType] [varchar](1) NULL, 
    [CondoCode] [varchar](1) NULL, 
    [Zip] [varchar](5) NULL, 
    [ZipSuffix] [varchar](4) NULL, 
    [StateAbbr] [varchar](2) NULL, 
    [DateImported] [datetime] NULL, 
    [RecordType] [varchar](1) NULL 
) ON [PRIMARY] 

调查,我的确发现与上表中相关的两个触发器:

ALTER TRIGGER [dbo].[ImportTempTable_ITrig] ON [dbo].[ImportTempTable] FOR INSERT AS 
/* 
* PREVENT NULL VALUES IN 'SaleMnYear' 
*/ 
IF (SELECT Count(*) FROM inserted WHERE SaleMnYear IS NULL) > 0 
    BEGIN 
     RAISERROR 44444 'Field ''SaleMnYear'' cannot contain a null value.' 
     ROLLBACK TRANSACTION 
    END 
ELSE 
/* 
* PREVENT NULL VALUES IN 'LenderName' 
*/ 
IF (SELECT Count(*) FROM inserted WHERE LenderName IS NULL) > 0 
    BEGIN 
     RAISERROR 44444 'Field ''LenderName'' cannot contain a null value.' 
     ROLLBACK TRANSACTION 
    END 

and

ALTER TRIGGER [dbo].[ImportTempTable_UTrig] ON [dbo].[ImportTempTable] FOR UPDATE AS 
/* 
* PREVENT NULL VALUES IN 'SaleMnYear' 
*/ 
IF (SELECT Count(*) FROM inserted WHERE SaleMnYear IS NULL) > 0 
    BEGIN 
     RAISERROR 44444 'Field ''SaleMnYear'' cannot contain a null value.' 
     ROLLBACK TRANSACTION 
    END 
ELSE 
/* 
* PREVENT NULL VALUES IN 'LenderName' 
*/ 
IF (SELECT Count(*) FROM inserted WHERE LenderName IS NULL) > 0 
    BEGIN 
     RAISERROR 44444 'Field ''LenderName'' cannot contain a null value.' 
     ROLLBACK TRANSACTION 
    END 

我不知道这些触发器是否到位。我会重新考虑它们存在的原因。也许这是多年来我们第一次得到“不良数据”,从而提出了这个愚蠢的错误。我认为上面列定义的NULL属性会允许NULL;这种触发方式似乎不明智。

在SQL中的实例级别是否有可以启用或禁用触发器的东西?我认为不...

多一点研究应该解决这个问题。

+0

你能告诉数据库查询和表结构?我认为'44444'是一个错误代码,它告诉'字段X不能包含空值'。检查您的查询是否尝试在执行批量更新时将空值插入到不可为空的列中,或者错误地附加到表的触发器(也检查触发器部分)。 –

+0

谢谢Tetsuya,我将展示表格结构。然而,数据库完整地迁移到SQL 2016的新实例。你是否知道任何实例级别的选项或配置选择可能对这个以前的工作程序有一些影响? –

+0

我想你的查询或数据库触发器处理中的某处可能包含以下语句:RAISERROR 44444'%message_text%''。您需要将其更改为SQL函数:'RAISERROR(44444,'%message_text%')'。 –

回答

1

Incorrect syntax near '44444'错误表示SQL触发器使用支持到SQL Server 2008 R2的未记录版本的RAISERROR语法。无证RAISERROR语法从SQL Server 2012年起已经不支持的,所以你需要使用支持RAISERROR syntax或使用THROW作为替代:

-- RAISERROR example 
RAISERROR(44444, -1, -1, 'Field ''SaleMnYear'' cannot contain a null value.'); 

-- THROW example 
THROW 44444, 'Field ''SaleMnYear'' cannot contain a null value.', 1; 

另外,你可以尝试下降两ImportTempTable_ITrig & ImportTempTable_UTrigImportTempTable触发然后设置列SaleMnYear & LenderName到不可为空的数据类型,不需要触发器,因为较新的SQL Server版本需要检查空值。

DROP TRIGGER IF EXISTS [dbo].[ImportTempTable_ITrig] 
DROP TRIGGER IF EXISTS [dbo].[ImportTempTable_UTrig] 

-- if the table already contains null value, update them first 
UPDATE [dbo].[ImportTempTable] SET SaleMnYear = {value}, LenderName = {value} 
WHERE SaleMnYear IS NULL {AND/OR} LenderName IS NULL 

ALTER TABLE [dbo].[ImportTempTable] ALTER COLUMN SaleMnYear {data_type} NOT NULL 
ALTER TABLE [dbo].[ImportTempTable] ALTER COLUMN LenderName {data_type} NOT NULL 

作为RecordSet.UpdateBatch其与上述错误暂停时,它假定运行ADO更新过程试图添加空值(一个或多个)到其中设置由如果条件有问题触发不允许空值或者SaleMnYearLenderName柱(确保源数据列中的记录不包含空值)。

注意:我建议使用ODBC ADODB.Connection上的托管SqlClient.SqlConnection来处理SQL Server连接实例。

参考:

Differences between RAISERROR and THROW in SQL Server

类似的问题:

Migrating from SQL Server 2008r2 to SQL Sever 2012

RAISERROR issue since migration to SQL Server 2012

+0

感谢您提供一流的答案! –