0

バーコード スキャナーを使用して 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 

助けてくれてありがとう。

4

1 に答える 1

0

あなたのコードは例外をスローしています。これにより、SQL Server は、関数から複数の値が返されていると見なされます。

おそらく、insert ステートメントに渡される値を正確に知りたいと思うでしょう (完全なリストのように)。重要な衝突の問題があるかどうかを知りたいです。

前のものと同じバーコードを挿入しないために使用している行は、そのようなことを避けようとしているようです。

于 2012-07-11T17:27:14.260 に答える