2017-09-06 105 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

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

相關問題