0

我有一个 SQLCLR 程序集,它创建一个带有条码扫描器的 Telnet 接口,并将它接收到的任何东西放在一个表中。有时,它会因错误而崩溃:

以用户身份执行:NT AUTHORITY\SYSTEM。
执行用户定义的例程期间发生 .NET Framework 错误
或聚合“fnBarcodeScanner”:  

System.Data.SqlClient.SqlException:子查询返回超过 1 个值。
当子查询跟随 =、!=、、>= 或
当子查询用作表达式时。  

System.Data.SqlClient.SqlException:      
  在 System.Data.SqlClient.SqlConnection.OnError(
       SqlException 异常,布尔型 breakConnection)     
  在 System.Data.SqlClient.SqlInternalConnection.OnError(
       SqlException 异常,布尔型 breakConnection)     
  在 System.Data.SqlClient.SqlInternalConnectionSmi.EventSink.DispatchMessages(
       布尔忽略非致命消息)     
  在 Microsoft.SqlServer.Server.SmiEventSink_Default.DispatchMessages(
       布尔忽略非致命消息)     
  在 System.Data.SqlClient.SqlCommand.RunExecuteNonQuerySmi(
       布尔 sendToPipe)     
  在 System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(
       DbAsyncResult 结果、String methodName、Boolean 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 认为您正在从函数返回多个值。

您可能想确切地知道将哪些值传递给您的插入语句(如在完整列表中)。我很想知道您是否有任何关键的碰撞问题。

您用来不插入与前一个相同的条形码的行似乎您正试图避免类似的事情。

于 2012-07-11T17:27:14.260 回答