如何编写存储过程以在多个表中插入值

时间:2013-08-05 19:24:21

标签: mysql sql stored-procedures

Database Schema

如何编写存储过程以添加多个地址的人员记录?

如果此人只有一个地址,但我不确定如何编写存储过程来添加具有多个地址的人,这很容易。 以下是添加具有一个地址的人员的存储过程:

 DELIMITER $$

 CREATE PROCEDURE `log`.`spAddPerson` (
 IN personID INT,
 IN personName VARCHAR(100),
 IN addressLine1 VARCHAR(45),
 IN addressLine2 VARCHAR(45),
 IN myCity VARCHAR(45),
 IN myState VARCHAR(45),
 IN myCountry VARCHAR(45)

 BEGIN
 DECLARE EXIT HANDLER FOR SQLEXCEPTION 
 BEGIN
      ROLLBACK;
 END;

 START TRANSACTION;

 INSERT INTO person VALUES(personID,personName);
 -- addressid is automatically generated
 INSERT INTO address(Line1, Line2,City,State,Country) VALUES
 (addressLine1, addressLine2, myCity,myState, myCountry);

 INSERT INTO personAddress(personID, last_insert_id());

 COMMIT;

 END

上面的代码工作正常。但是,我不知道如何处理具有多个地址的人而无需编写单独的存储过程。有一种简单的方法可以做到这一点吗?

2 个答案:

答案 0 :(得分:1)

您不能将可变数量的变量传递给过程,也不能传递非标量类型。

一个可能的技巧是在调用此过程之前构建一个包含地址的临时表。临时表是预先确定的,或者将其名称作为VARCHAR参数传递(并使用它来构建动态SQL语句)。例如:

CREATE PROCEDURE spAddPerson (tmp_table VARCHAR(10), ...)
BEGIN
    ...
    PREPARE s AS CONCAT(
        'INSERT INTO address (line1, ...) VALUES SELECT * FROM ', tmp_table
    );
    EXECUTE s;
    ...
END


-- use it like this
CREATE TEMPORARY TABLE tmp_addresses (line1 VARCHAR(255), ...);
INSERT INTO tmp_addresses VALUES ('1 Cherry Lane'), ... ;
CALL spAddPerson ('tmp_addresses', ...);

但是,我宁愿将行动分为两部分。如果地址创建失败,您真的想要完全阻止person的创建吗?即便如此,您是否想要告知您的用户交易失败的原因(用户创建或地址创建)?

我宁愿在应用程序级别单独处理这两个例外:


    issue a "START TRANSATION"
    try to insert a person (call stored proc 1)
    if it failed, rollback and notify user
    for each address
        try to insert an address (call stored proc 2)
        if it failed, rollback and notify user
    issue a "COMMIT"

答案 1 :(得分:0)

>     DECLARE @LAST_INSERT_ID INT
>     DECLARE @EXECUTION_OK char(1)
>     SET @EXECUTION_OK = 1
>     
>     insert into base_table(imgPath,store,apparelType) values (imgPath,store,apparelType)
>     
>         SELECT @LAST_INSERT_ID = SCOPE_IDENTITY()
>         
>         insert into data_table(cvID,color) values (@LAST_INSERT_ID, color)
>         GO
>         
>         If exists( Select cvID from data_table where cvID= @LAST_INSERT_ID)
>         Begin
>         @EXECUTION_OK = 0
>         End