如何在存储过程中声明行不存在?

时间:2018-11-11 10:16:44

标签: sql sql-server

我想知道某个QuestionIDEmployeeID是否存在;如果这样做,则需要像下面这样插入它们(工作正常)。

但是,如果它们不存在,我希望为用户提供一个好消息,以便他知道QuestionIDEmployeeID或两者都不存在。还可能回滚该交易吗?现在我可以添加每个数字,但是存储过程仍然完成了命令...

我有以下代码(我正在使用SQL Server):

CREATE PROCEDURE Contentment
    @employeeID INT,
    @questionid INT
AS
BEGIN
    IF EXISTS (SELECT questionid 
               FROM question 
               WHERE questionid = @questionid)
        IF EXISTS (SELECT employeeID 
                   FROM employee 
                   WHERE employeeid = @employeeID)
        BEGIN
            INSERT INTO contentment (employeeid, questionid, date, score, comment)
            VALUES (@employeeID, @questionid, null, null, null)
        END
        ELSE
            IF @employeeID = 0
                RAISERROR ('-certain error-', 16, 1, @employeeid) 

    IF @questionid = 0
        RAISERROR ('-certain error-', 16, 1, @questionid)           
END

3 个答案:

答案 0 :(得分:0)

我会尝试这样做-在单个语句中检查两个参数的存在-如果不存在,则提供错误:

CREATE PROCEDURE dbo.Contentment
    @employeeID INT,
    @questionid INT
AS
BEGIN
    -- check for *both* conditions at once
    IF EXISTS (SELECT * FROM dbo.question WHERE questionid = @questionid) AND
       EXISTS (SELECT * FROM dbo.employee WHERE employeeid = @employeeID)
    BEGIN
        -- if OK --> insert
        INSERT INTO dbo.contentment (employeeid, questionid, date, score, comment)
        VALUES (@employeeID, @questionid, null, null, null)
    END
    ELSE
    BEGIN
        -- if NOT OK --> provide error
        RAISERROR ('@EmployeeID or @QuestionID do not exist', 16, 1, null) 
    END
END
  

也可能回滚该交易吗?

由于您实际上并没有做任何事情(两个ID中的任何一个都不存在INSERT,所以在这一点上确实没有任何事务可以回滚。...

答案 1 :(得分:0)

您可以使用类似这样的错误消息参数:

scale_x_date()

不要使用ROLLBACK,因为您处理了NULL值

答案 2 :(得分:0)

我会让数据库完成工作。声明表具有适当的外键关系:

alter table contentment add constraint fk_conententment_question
    foreign key (questionid) references question(questionid);

alter table contentment add constraint fk_conententment_employee
    foreign key (employeeid) references employee(employeeid);

然后将过程编写为:

CREATE PROCEDURE dbo.usp_Contentment (
    @employeeID INT,
    @questionid INT
) AS
BEGIN
    INSERT INTO dbo.contentment (employeeid, questionid, date, score, comment)
        VALUES (@employeeID, @questionid, null, null, null)
END;  -- usp_Contentment

数据库将生成一个错误,即外键关系失败-如果没有匹配的键。

由于以下几个原因,这种方法比自己进行测试要好得多:

  • 数据库可确保数据完整性,因此无论数据发生在何处,您都将保持关系。
  • 完整性适用于insertupdate。无需将支票放在多个地方。
  • 完整性检查是线程安全的,因此,如果在引用表中修改行,则完整性检查会起作用。

如果您确实想要自定义消息,则可以在try / catch块中捕获错误,并获得自定义错误。