【问题标题】:deleting the data after copying it into another database将数据复制到另一个数据库后删除
【发布时间】:2014-07-11 23:28:55
【问题描述】:

我有一个存储过程,其内容如下:

-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$

CREATE DEFINER=`MailMe`@`%` PROCEDURE `sp_archivev3`()
BEGIN

INSERT INTO 
     send.sgev3_archive(a_bi,
                        b_vc,
                        c_int,
                        d_int,
                        e_vc,
                        f_vc,
                        g_vc,
                        h_vc,
                        i_dt,
                        j_vc,
                        k_vc,
                        l_vc,
                        m_dt,
                        n_vch,
                        o_bit)
SELECT     a_bi,
           b_vc,
           c_int,
           d_int,
           e_vc,
           f_vc,
           g_vc,
           h_vc,
           i_dt,
           j_vc,
           k_vc,
           l_vc,
           m_dt,
           n_vch,
           o_bit

FROM   send.sgev3

WHERE m_dt BETWEEN  '2014-06-09' AND CURDATE();


END

因为,我的查询是将记录从send.sgev3 插入到send.sgev3_archive。我还想做一件事。在选择 send.sgev3 表中的记录并将其插入send.sgev3_archive 后,我想删除它们。我应该在上面的代码中的 SELECT 查询下面写 DELETE 查询吗?只是想确认一下,因为我不想弄乱我的真实数据并在不复制的情况下意外删除任何记录。请指教。

【问题讨论】:

  • 特别是如果m_dt 真的是一个时间戳,你不应该使用the inclusive upper-bound of BETWEEN。您还需要在两个语句中使用 same value 作为上限,因此首先需要单独获取它。就此而言,您可能希望能够将范围传递给您的存储过程,而不仅仅是使用预定义的范围。

标签: mysql sql stored-procedures


【解决方案1】:

没错。包括一个DELETE 声明

DELETE FROM   send.sgev3
WHERE m_dt BETWEEN  '2014-06-09' AND CURDATE();

为了更确定INSERT 确实在DELETE 调用之前完成;将INSERTDELETE 包装在Transaction Block

START TRANSACTION;
INSERT INTO send.sgev3_archive ...
SELECT ... FROM send.sgev3
COMMIT;

您还可以使用exit handler in stored procedure 处理您的过程和ROLLBACK 整个事务中的错误情况。下面的帖子已经展示了一种方法。看看吧。

How can I use transactions in my MySQL stored procedure?

MySQL Rollback in transaction

编辑:

为什么需要交易?我不能像我一样继续前进吗 我的问题中提到了?

而不是向你解释原因;让我们给你看一个例子(很像你的场景)

假设您有一个名为parent 的表声明为

create table parent(id int not null auto_increment primary key,
`name` varchar(10),city varchar(10));

向其中插入一些记录

insert into parent(`name`,city) values('sfsdfd','sdfsdfdf'),('sfsdfd','sdfsdfdf'),('sfsdfd',null)

现在,您有另一个名为child 的表定义如下(注意最后一列有not null 约束)

create table child(id int not null auto_increment primary key,
`name` varchar(10),city varchar(10) not null) 

现在执行以下两个语句(您当前正在执行的操作)

insert into child(`name`,city) select * from parent;
delete from parent;

结果:INSERT 将因child 表中的not null 约束而失败,但delete 将成功。

为了避免这种确切的情况,您需要Transaction。因此,如果 INSERT 失败,您根本不会选择 delete

关于如何在事务中处理此问题的伪代码

start transaction

insert into child(`name`,city) select * from parent;

if(ERROR)
rollback
exit from stored proc

else
commit
delete from parent;

旁注:exit from stored proc 可以使用LEAVE 实现

【讨论】:

  • 好的,我将在SELECT 语句之后包含DELETE a_bi,b_vc.... etc。顺便说一下,在更多问题上,假设存储过程要按顺序运行语句,它应该首先运行INSERTSTATEMENT,然后是SELECT,然后是DELETE。不应该是先SELECTINSERTDELETE吗?
  • 你说得对。它将选择行,然后将它们插入insert into select from
  • 但是我在上面的查询中做相反的事情,它现在仍在工作,没有删除任何数据(这很明显,因为我没有 DELETE 命令在那里)。我想知道为什么?更清楚地说,为什么我上面的查询要先运行 SELECT 命令,然后将其作为 SELECT 命令插入在下面的 INSERT 中。
  • 不,你不是。阅读有关insert into select from 的 MySQL 文档以澄清它。顺便说一句,没有冒犯,但我记得,回答您早期的 MySQL 事件相关问题之一;您没有提供任何反馈。只是一个建议:不要那样做。如果您觉得答案与您正在寻找的不符,请说出来,否则请接受答案以表示感谢。
  • 为每个语句使用单独的事务有什么意义?
猜你喜欢
  • 1970-01-01
  • 2018-02-24
  • 2017-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-16
  • 1970-01-01
相关资源
最近更新 更多