2011-01-10 192 views
4

这是我的SP存储过程将不会返回0

CREATE PROCEDURE DeteleTitle 
(
@TitleID int 
) 
AS 
BEGIN 
IF EXISTS(Select TitleID from Titles WHERE [email protected]) 
BEGIN 
DELETE FROM Titles WHERE [email protected] 
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东西”。在我上面的存储过程中,如果delete不成功,我在else块中选择零。当删除成功时,它会返回TitleID的值,如50,99或其他。现在发生的是,当删除不成功时,它不返回零。我想根据删除存储过程返回的零值显示一条消息,但是当它没有返回任何值时(删除失败时),我在DeleteTitle()方法的catch块中返回零。

现在我有两个问题: -

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

你应该至少抓住一个sqlexception(我相信这是正确的,如果不查找它)。目前你在这里可能会捕捉所有不相关的异常,并忽略它们。您应该确实捕获特定的异常,以便任何意外的异常可以冒泡到应用程序级别的错误处理程序,以适当处理和记录以及其他任何内容。 – Chris 2011-01-10 18:42:17

回答

3

你想在你的程序中使用TRY...CATCH,而不是IF ... ELSE。

如果您仔细考虑过,当DELETE失败且外键违规时,您已经在语句的IF部分。你的代码如何可能跳转到ELSE块?

3

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

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

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

+0

你是对的..它是如果只存在..是一个错字..我纠正它。一个问题 - 许多使用该TitleID作为外键的表有什么方法?仍在所有这些表中明确检查?请回答..thnx – Serenity 2011-01-10 18:51:04

2

如果Tables是表的集合,那么对于第一个表的第一列,您需要另一个[0]

+0

在我看来,表格实际上是由Execute Scalar方法返回的“对象”。我期望它会抛出一个异常(或可能不实际编译),因为在返回的对象上不会有名为“Table”的属性或方法。但我可能是错的。 :) – Chris 2011-01-10 18:39:35

2

使用本:

CREATE PROCEDURE DeteleTitle 
(
@TitleID int 
) 
AS 
BEGIN TRY 
    DELETE FROM Titles WHERE [email protected] 
    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 [email protected] 
    DELETE FROM YourOtherTablesB WHERE [email protected] 

    DELETE FROM Titles WHERE [email protected] 
    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 
0

您可以使用@@ ERROR作为输出结果。 @@ ERROR = 0意味着成功,否则不成功的操作

CREATE PROCEDURE DeteleTitle 
(
    @TitleID int 
) 
AS 

BEGIN 
    IF EXISTS(Select TitleID from Titles WHERE [email protected]) 
    BEGIN 
     DELETE FROM Titles WHERE [email protected]  
    END 

    Select @@ERROR 

END