【问题标题】:SQL Stored Procudure returning no valueSQL 存储过程不返回任何值
【发布时间】:2011-06-09 22:04:15
【问题描述】:

我必须关注 sproc:

USE [CW]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[addCustomer]
@firstname VARCHAR(50) = '',
@lastname VARCHAR(50) = '',
@email VARCHAR(50) = '',
@password VARCHAR(50) = ''


AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;
SELECT * FROM customer WHERE email = @email

IF (@@ROWCOUNT = 0)
    BEGIN
        -- Add to database.
        INSERT INTO customer (firstname, lastname, email, [password]) 
        VALUES (@firstname, @lastname, @email, @password);
        SELECT @@IDENTITY;
    END
ELSE
    BEGIN
        -- Don't add already registered
        SELECT customer.customerID FROM customer WHERE email = @email;
    END


END

将客户添加到表中。如果他们的电子邮件已经在表中,它会返回该客户的 ID。如果电子邮件不在表中,它会创建它并返回新的 id。

问题是,当它创建新记录时,它返回 null。但是当我在 Management Studio 中执行存储过程时,它会显示正确的返回值。

代码如下:

            SqlCommand cmd0 = new SqlCommand();
            cmd0.Connection = conn;
            cmd0.CommandType = CommandType.StoredProcedure;
            cmd0.CommandText = "addCustomer";
            cmd0.Parameters.AddWithValue("@firstname", firstname);
            cmd0.Parameters.AddWithValue("@lastname", lastname);
            cmd0.Parameters.AddWithValue("@email", email);
            cmd0.Parameters.AddWithValue("@password", password);

            var scaled = cmd0.ExecuteScalar();
            customerID = scaled.ToString();

当电子邮件唯一时,customerID 为空。

【问题讨论】:

标签: c# .net sql sql-server stored-procedures


【解决方案1】:

您返回的不是标量,而是从表中选择的,这是不同的。你想要一个RETURN 声明。另一种方法是使用OUTPUT 参数。您可以将 C# 中的参数设置为输出参数,运行过程后,您可以从中读取值。

【讨论】:

    【解决方案2】:

    试试这个:

    ALTER PROCEDURE [dbo].[addCustomer]
        @firstname VARCHAR(50) = '',
        @lastname VARCHAR(50) = '',
        @email VARCHAR(50) = '',
        @password VARCHAR(50) = ''
    AS
    
    SET NOCOUNT ON;
    
    IF NOT EXISTS (SELECT * FROM customer WHERE email = @email)
        INSERT INTO customer (firstname, lastname, email, [password]) 
        VALUES (@firstname, @lastname, @email, @password);
    
    SELECT customer.customerID FROM customer WHERE email = @email;
    
    GO
    

    【讨论】:

      【解决方案3】:

      else 是多余的,第一个 select 语句正在做同样的事情。我认为 executescalar 使用的是第一个结果集而不是第二个结果集,因此不是 @@identity。

      先使用这个查询

      SELECT customer.customerID FROM customer WHERE email = @email;

      并摆脱其他。然后按照其他答案的建议使用返回值方法。

      【讨论】:

        【解决方案4】:

        授予,

        使用@@ROWCOUNT 不是确保尚未输入客户的正确方法。它只是告诉你,当你检查时客户不在桌子上。

        正确的方法是对电子邮件列应用唯一约束。然后尝试插入客户行。如果该行插入,则输入客户。如果您遇到唯一违规,则说明客户已经存在,您可以选择/返回 customerID。

        一旦可行,就按照 Nik 已经说过的去做。

        【讨论】:

        • 如果您不这样做,那么您要么必须在插入期间锁定所有资源,要么您需要处理在不同进程插入时会出现的密钥冲突在您检查时间和插入时间之间的客户。无论哪种方式,您都必须处理密钥违规。您不妨提前做好。
        • 如果您有两个独特的字段,您将永远不知道是哪一个造成了问题。
        猜你喜欢
        • 1970-01-01
        • 2014-05-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-23
        • 1970-01-01
        • 2011-04-26
        相关资源
        最近更新 更多