バーコード スキャナーを使用して Telnet インターフェイスを作成し、受信したものをすべてテーブルに配置する SQLCLR アセンブリがあります。ときどき、次のエラーでクラッシュします。
ユーザーとして実行: NT AUTHORITY\SYSTEM。 ユーザー定義ルーチンの実行中に .NET Framework エラーが発生しました または集約「fnBarcodeScanner」: System.Data.SqlClient.SqlException: サブクエリが複数の値を返しました。 サブクエリが =、!=、、>= または サブクエリが式として使用されている場合。 System.Data.SqlClient.SqlException: System.Data.SqlClient.SqlConnection.OnError で ( SqlException 例外、ブール値の breakConnection) System.Data.SqlClient.SqlInternalConnection.OnError で ( SqlException 例外、ブール値の breakConnection) System.Data.SqlClient.SqlInternalConnectionSmi.EventSink.DispatchMessages で ( ブール値の ignoreNonFatalMessages) Microsoft.SqlServer.Server.SmiEventSink_Default.DispatchMessages ( ブール値の ignoreNonFatalMessages) System.Data.SqlClient.SqlCommand.RunExecuteNonQuerySmi で ( ブール sendToPipe) System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery で ( DbAsyncResult の結果、文字列の methodName、ブール値の sendToPipe) System.Data.SqlClient.SqlCommand.ExecuteNonQuery() で MinimalisticTelnet.Program.Connect(String ip) で。 [SQLSTATE 42000] (エラー 6522) ステートメントは終了しました。 [SQLSTATE 01000] (エラー 3621)。ステップは失敗しました。
エラーの意味は理解できますが、この場合、エラーがどのように発生しているのかわかりません。アセンブリ内の唯一の 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
助けてくれてありがとう。