我有一個SQLCLR程序集,它使用條形碼掃描程序創建Telnet接口,並將收到的任何東西放置在表中。偶爾,它崩潰,出現錯誤:「子查詢返回多個值」在SQLCLR程序集上
Executed as user: NT AUTHORITY\SYSTEM. A .NET Framework error occurred during execution of user-defined routine or aggregate "fnBarcodeScanner": System.Data.SqlClient.SqlException: Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, , >= or when the subquery is used as an expression. System.Data.SqlClient.SqlException: at System.Data.SqlClient.SqlConnection.OnError( SqlException exception, Boolean breakConnection) at System.Data.SqlClient.SqlInternalConnection.OnError( SqlException exception, Boolean breakConnection) at System.Data.SqlClient.SqlInternalConnectionSmi.EventSink.DispatchMessages( Boolean ignoreNonFatalMessages) at Microsoft.SqlServer.Server.SmiEventSink_Default.DispatchMessages( Boolean ignoreNonFatalMessages) at System.Data.SqlClient.SqlCommand.RunExecuteNonQuerySmi( Boolean sendToPipe) at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery( DbAsyncResult result, String methodName, Boolean sendToPipe) at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() at MinimalisticTelnet.Program.Connect(String ip) . [SQLSTATE 42000] (Error 6522) The statement has been terminated. [SQLSTATE 01000] (Error 3621). The step failed.
我明白了什麼錯誤意思,但我不知道它是如何在這種情況下所引起。程序集中唯一的SQL是一個插入語句,它在表中插入一個字符串。應該沒有辦法擁有多個價值。下面是用於組件的C#代碼(包括爲簡潔起見省略了):
namespace MinimalisticTelnet
{
public class Program
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void Main(string[] args)
{
}
public static void Connect(String ip)
{
String lastCode = null;
TelnetConnection tc = new TelnetConnection(ip, 23);
using (SqlConnection conn = new SqlConnection("context connection=true"))
{
SqlCommand InsertID = new SqlCommand();
InsertID.Connection = conn;
SqlParameter IDCodeParam = new SqlParameter("@Barcode", SqlDbType.VarChar);
conn.Open();
while (tc.IsConnected)
{
String barcode = tc.Read();
if (!((barcode).Length == 0))
{
barcode = barcode.Substring(0,barcode.IndexOf("\n") - 1);
if (!(barcode == lastCode))
{
lastCode = barcode;
SqlString sqlBarcode = barcode;
IDCodeParam.Value = sqlBarcode;
InsertID.Parameters.Add(IDCodeParam);
InsertID.CommandText = "INSERT INTO dbo.tbl_Barcode (Barcode)" +
" Values(@Barcode)";
InsertID.ExecuteNonQuery();
InsertID.Parameters.Clear();
}
}
}
conn.Close();
}
}
}
}
這裏是fnBarcodeScanner的代碼:
CREATE PROCEDURE [dbo].[fnBarcodeScanner]
@ip [nvarchar](20)
WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [Telnet].[MinimalisticTelnet.Program].[Connect]
GO
在這裏被觸發:
ALTER TRIGGER [dbo].[trg_Barcode]
ON [dbo].[tbl_Barcode]
AFTER INSERT
AS
BEGIN
DECLARE @MVID INT,
@P VARCHAR(25),
@NewLane VARCHAR(10),
@TC INT,
@DID INT,
@AD DATE,
@AT VARCHAR(18),
@TrayCount INT,
@DivertCount INT,
@ScanID VARCHAR(50),
@PID INT,
@cDivert VARCHAR(8)
SET @ScanID = (SELECT Barcode
FROM tbl_Barcode)--Barcode Value
SET @MVID = (SELECT MVID
FROM tbl_Divert
WHERE Barcode = @ScanID)--JOT Version ID
SET @P = (SELECT PalletNbr
FROM tbl_Divert
WHERE Barcode = @ScanID)--Pallet Number
SET @PID = (SELECT PalletID
FROM tbl_Pallet_Verification
INNER JOIN tbl_Pallet_Mailing
ON tbl_Pallet_Verification.MailingID = tbl_Pallet_Mailing.MailingID
WHERE tbl_Pallet_Mailing.MVID = @MVID
AND tbl_Pallet_Verification.PalletNum = @P)--PAT Pallet ID
SET @AD = (Cast(CONVERT(VARCHAR(10), Getdate(), 110) AS DATE))--Today's Date
SET @AT = CONVERT(TIME, Getdate())--Current Time
SET @cDivert = (SELECT Divert
FROM tbl_Divert
WHERE Barcode = @ScanID)
SET @NewLane = (SELECT TOP 1 ID
FROM tbl_Tray_Lanes
WHERE LaneActive = -1
AND ID NOT IN(SELECT Divert
FROM tbl_Pallet_Lanes
WHERE DateCompleted IS NULL))--Find Open Lane
SET @TC = (SELECT Count(TrackerID)
FROM tbl_Divert
WHERE MVID = @MVID
AND PalletNbr = @P)--Tray Count
SET @TrayCount = (SELECT Count(TrackerID)
FROM tbl_Divert
WHERE Barcode = @ScanID)--Is Tray Found in Divert Table
SET @DivertCount = (SELECT Count(TrackerID)
FROM tbl_Divert
WHERE Barcode = @ScanID
AND Divert IS NOT NULL)--Verify Tray has not been scanned
--Add Date/Time to Tray Record. This will mark tray as scanned
SELECT TrackerID
FROM tbl_Divert
WHERE Barcode = @ScanID
AND Divert IS NULL
IF @@ROWCOUNT > 0
BEGIN
SET NOCOUNT ON;
IF @NewLane IS NOT NULL
BEGIN --Add Available lane to Lane Table and give tray record the LaneID
IF @TrayCount > 0 --Verify tray record exist
BEGIN
--IF @DivertCount = 0 --If not previously scanned
--Begin--Insert Lane Record
INSERT INTO tbl_Pallet_Lanes
(MVID,
PalletID,
PalletNbr,
Divert,
TrayCount,
DateStarted,
TimeStarted)
SELECT @MVID,
@PID,
@P,
@NewLane,
@TC,
@AD,
@AT
--Get LaneID
SET @DID = (SELECT ID
FROM tbl_Pallet_Lanes
WHERE MVID = @MVID
AND PalletNBR = @P)
--Add LaneID to tray record
UPDATE tbl_Divert
SET Divert = @NewLane,
DivertID = @DID
WHERE MVID = @MVID
AND PalletNbr = @P
--END
END
END
IF @NewLane IS NULL
BEGIN --If there is no open lane assign Lane 16. This will send the tray to end of tray tracker for
--manual pallet load.
UPDATE tbl_Divert
SET Divert = 16,
DivertID = 0
WHERE MVID = @MVID
AND Barcode = @ScanID
END
END
DELETE FROM tbl_Barcode --Clear barcode table
UPDATE tbl_Divert
SET Scanned = @AD,
ScanStatus = 1 --Scan Status Flags which Reader
WHERE Barcode = @ScanID
END
由於尋求幫助。
你對'tbl_Barcode'有觸發器嗎?它的設計目的是一次只處理一行? – HABO 2012-07-11 17:19:33
只是爲了清理:你還應該在SqlCommand上有一個USING子句;你可以擺脫conn.Close()調用。 SqlConnection上的使用將爲您做到這一點。 – NotMe 2012-07-11 17:20:20
任何引用完整性查詢是否會自動執行,可能導致此問題?您是否嘗試過使用查詢分析器查看SQL跟蹤?有時會執行比您預期更多的查詢。 – 2012-07-11 17:21:55