存储过程不会返回0

时间:2011-01-10 18:11:04

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

这是我的sp

CREATE PROCEDURE DeteleTitle
(
@TitleID int
)
AS
BEGIN
IF EXISTS(Select TitleID from Titles WHERE TitleID=@TitleID)
BEGIN
DELETE FROM Titles WHERE  TitleID=@TitleID
SELECT @TitleID
END
ELSE
BEGIN
SELECT 0
END
END

我称之为的方法是: -

public Int32 DeleteTitle(Int32 TitleID)
{
try
{
int ds=0;
SqlParameter[] sqlparam=new SqlParameter[1];
sqlparam[0]=(@TitleID,TitleID);
ds=Convert.ToInt32(SqlHelper.ExecuteScalar(ConfigurationManager.ConnectionStrings["con"].ConnectionString,CommandType.StoredProcedure,"DeleteTitle",sqlparam).Tables[0]);
return ds;
}

catch(Exception ex)
{
return 0;
}
}

现在TitleID是许多表中的外键。如果某些Table的记录使用的是TitleID,那么它会抛出这个异常,说“外键违规n东西”。在我上面的存储过程中,我在else块中选择零,以防删除不成功。当删除成功时,它返回TitleID的值,如50,99或其他。现在发生的事情是,当删除不成功时,它不会返回零。我希望根据Delete Stored过程返回的零值在屏幕上显示一条消息,但是当它没有返回任何值时(当删除失败时),我在DeleteTitle()方法的catch块中返回零。

现在我有两个问题: -

  1. 为什么删除失败时存储过程不返回零?
  2. 在catch块中返回零,就像我在正确的方向上做的那样?我不知道你是如何检索外键的Exception数字和东西所以我只是在catch块中返回零。

5 个答案:

答案 0 :(得分:3)

您需要在程序中使用TRY...CATCH,而不是IF ... ELSE。

如果您考虑一下,当DELETE因外键违规而失败时,您已经在语句的IF部分。您的代码怎么可能跳转到ELSE块?

答案 1 :(得分:3)

问题是如果if语句因异常而失败,那么它将不会执行ELSE语句。您的IF语句也显示不正确 - 不应该是IF EXISTS,[然后删除记录?]现在写的方式,如果记录存在则不会被删除。

扩展的问题是,依赖异常(使用C#,SQL或任何其他语言)作为流控制的方法被认为是不好的做法。

通过对每个相关表使用EXISTS语句,最好显式检查相关记录。

答案 2 :(得分:2)

如果Tables是表的集合,则第一个表的第一列需要另一个[0]

答案 3 :(得分:2)

使用它:

CREATE PROCEDURE DeteleTitle
(
@TitleID int
)
AS
BEGIN TRY
    DELETE FROM Titles WHERE TitleID=@TitleID
    SELECT CASE 
               WHEN @@ROWCOUNT>0 THEN @TitleID 
               ELSE 0 --row did not exist
           END
END TRY
BEGIN CATCH
    SELECT 0 --delete failed
END CATCH
go

当多个表通过外键“链接”并删除父行时,会出现类似于报告的错误,因为子数据在没有父项的情况下不能存在。您可能希望查看级联删除,或在此过程中添加代码以从通过外键与标题关联的表中删除。在DELETE FROM Titles之前添加这些删除。这样做:

CREATE PROCEDURE DeteleTitle
(
@TitleID int
)
AS
BEGIN TRY
    BEGIN TRANSACTION

    DELETE FROM YourOtherTablesA WHERE TitleID=@TitleID
    DELETE FROM YourOtherTablesB WHERE TitleID=@TitleID

    DELETE FROM Titles WHERE TitleID=@TitleID
    SELECT CASE 
               WHEN @@ROWCOUNT>0 THEN @TitleID 
               ELSE 0 --row did not exist
           END
    COMMIT
END TRY
BEGIN CATCH
    IF XACT_STATE()!=0
    BEGIN
        ROLLBACK TRANSACTION
    END
    SELECT 0 --delete failed
END CATCH
go

答案 4 :(得分:0)

您可以使用@@ ERROR作为输出结果。 @@ ERROR = 0表示其他成功的操作失败

CREATE PROCEDURE DeteleTitle
(
    @TitleID int
)
AS

BEGIN
    IF EXISTS(Select TitleID from Titles WHERE TitleID=@TitleID)
    BEGIN
        DELETE FROM Titles WHERE  TitleID=@TitleID      
    END

    Select @@ERROR

END