mysql用存储过程写入 一个表A中没有存在在另一个表B的数据

本文介绍了如何使用MySQL查询语句及存储过程实现两表间数据比对与同步,具体包括运用NOT IN、NOT EXISTS等条件筛选不同步的数据项,并通过INSERT INTO SELECT实现数据自动填充。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

需求

Abiao
id      content
1        sfsdfsg
2       ddsgffd
3       gfggg
4       dggfhfd

Bbiao 

id      

2
3

那么我要查询到Abiao 里面在Bbiao没有的数据
(理想结果)就是:
id       content
1        sfsdfsg
4       dggfhfd


1.mysql 查询一个表中没有存在在另一个表的数据

SELECT * FROM A 
WHERE  id  NOT  IN  ( SELECT id FROM B);
 
或者
SELECT * FROM A 
WHERE 
    NOT  EXISTS  ( 
        SELECT 1 
        FROM B 
        WHERE B.id = A.id );
 
或者
SELECT 
  A.* 
FROM 
  A  LEFT JOIN B
    ON (A.id = B.id)
WHERE
  b.id  IS  NULL

2.用存储过程根据查询出来的结果(一个表A中没有存在在另一个表B的数据  )循环插入

BEGIN
	

  DECLARE i_UserID int default 0; -- 加盟商ID
  DECLARE i_UserName VARCHAR(32) default '0';  -- 账号
  DECLARE i_Mobile VARCHAR(32) default '0';  -- 手机号码
  DECLARE i_Sex int default 0; -- 性别
	DECLARE i_UserRank int default 0; -- 用户等级
	DECLARE i_RegTime int default 0; -- 注册时间

  DECLARE done INT DEFAULT 0;
  -- 循环跳出标志
  DECLARE cur_agent CURSOR FOR 
  SELECT user_id,user_name,mobile,sex,user_rank,reg_time FROM dreamytaste.mw_users 
	WHERE  user_id  NOT  IN  ( SELECT UserID FROM jaclub.bbm_capital_users);
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE ;
  -- 空游标改变跳出标识


	-- 获取显示时间
  OPEN cur_agent;
  -- 启动游标
	


	read_loop :-- 循环处理
  LOOP
    FETCH cur_agent INTO 
    i_UserID,
		i_UserName,
    i_Mobile,
		i_Sex,
		i_UserRank,
		i_RegTime;

    IF done 
    THEN LEAVE read_loop ;
    END IF ;

    -- 处理数据 --写入bbm_agent_capital_count
    insert into `bbm_capital_users` (
      UserID,
      SiteID,
      UserName,
      Mobile,
      Sex,
			UserRank,
			UserStatus,
			RegTime,
			JaclubUserName

    ) 
    values
      (
        i_UserID,
        0,
        i_UserName,
        i_Mobile,
        i_Sex,
        i_UserRank,
				1,
				i_RegTime,
				i_UserName
				
				
      ) ;
		
  END LOOP ;

END

3.更简单的方法,用insert into select

select into from 和 insert into select都是用来复制表,两者的主要区别为: select into from 要求目标表不存在,因为在插入时会自动创建。insert into select from 要求目标表存在
 
 
下面分别介绍两者语法
 
 
一、INSERT INTO SELECT语句
 
 
1、语句形式为
 
Insert into Table2(field1,field2,...) select value1,value2,... from Table1
 
 
2、注意地方
 
(1)要求目标表Table2必须存在,并且字段field,field2...也必须存在
 
(2)注意Table2的主键约束,如果Table2有主键而且不为空,则 field1, field2...中必须包括主键
 
(3)注意语法,不要加values,和插入一条数据的sql混了,不要写成:
  Insert into Table2(field1,field2,...) values (select value1,value2,... from Table1)
 
(4)由于目标表Table2已经存在,所以我们除了插入源表Table1的字段外,还可以插入常量。
 
 
3、完整实例:
 
 
 
SQL 代码   复制

    --1.创建测试表
    create TABLE Table1
    (
         a varchar(10),
         b varchar(10),
         c varchar(10),
         CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED
         (
             a ASC
         )
    ) ON [PRIMARY]
 
    create TABLE Table2
    (
         a varchar(10),
         c varchar(10),
         d int,
         CONSTRAINT [PK_Table2] PRIMARY KEY CLUSTERED
         (
             a ASC
         )
    ) ON [PRIMARY]
    GO


    --2.创建测试数据
    Insert into Table1 values('','asds','90')
    Insert into Table1 values('','asds','100')
    Insert into Table1 values('','asds','80')
    Insert into Table1 values('','asds',null)
    GO
    select * from Table2
 

    --3.INSERT INTO SELECT语句复制表数据
    Insert into Table2(a, c, d) select a,c,5 from Table1
    GO
 

    --4.显示更新后的结果
    select * from Table2
    GO


    --5.删除测试表
    drop TABLE Table1
    drop TABLE Table2

 

二、SELECT INTO FROM语句

 

语句形式为:SELECT vale1, value2 into Table2 from Table1
 
要求目标表Table2不存在,因为在插入时会自动创建表Table2,并将Table1中指定字段数据复制到Table2中 。
 
 
完整实例:
 
 
 
SQL 代码   复制

    --1.创建测试表
     create TABLE Table1
    (
         a varchar(10),
         b varchar(10),
         c varchar(10),
         CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED
         (
             a ASC
         )
    ) ON [PRIMARY]
    GO
 

    --2.创建测试数据
     Insert into Table1 values('','asds','90')
    Insert into Table1 values('','asds','100')
    Insert into Table1 values('','asds','80')
    Insert into Table1 values('','asds',null)
    GO
 

    --3.SELECT INTO FROM语句创建表Table2并复制数据
     select a,c INTO Table2 from Table1
    GO
 

    --4.显示更新后的结果
     select * from Table2
    GO


    --5.删除测试表
     drop TABLE Table1
    drop TABLE Table2


<think>好的,用户的问题是关于如何在MySQL存储过程中调用一个存储过程并将结果插入到临时。我需要仔细分析这个问题,并给出正确的示例和步骤。 首先,我应该回忆一下MySQL存储过程的基本知识。存储过程可以调用其他存储过程,但直接获取结果集可能比较困难,因为存储过程能直接返回结果集供一个存储过程处理。过,用户提到使用临时,这可能是一个解决方法。 接下来,临时存储过程中的使用。临时只在当前会话中存在,会话结束后自动删除,适合用来暂存中间数据。用户需要将一个存储过程的结果插入到临时中,可能需要先创建临时的结构,然后通过某种方式将数据写入其中。 但问题来了,存储过程A调用存储过程B,B产生的结果集如何传递给临时呢?直接调用可能行,因为存储过程的结果集是直接返回给客户端的,而是给一个存储过程。这时候可能需要使用游标来处理结果集,或者让存储过程B将结果插入一个临时中,而是直接返回结果集。 根据引用[4],临时可以用于存储查询结果。因此,可能的步骤是: 1. 在存储过程中创建临时。 2. 调用一个存储过程,该存储过程将结果插入到临时中,或者使用游标获取结果集并插入。 3. 处理临时中的数据。 但如何让被调用的存储过程将结果存入临时呢?或许,在调用存储过程B之前,先创建临时,然后在存储过程B中执行INSERT INTO临时的操作。但这样需要存储过程B知道临时的结构,可能太灵活。 一种方法是使用游标。在存储过程A中调用存储过程B,然后使用游标获取B的结果集,逐行插入到临时中。但存储过程的结果集通常需要被处理,比如使用游标来遍历结果。 或者,可能存储过程B在内部直接将数据插入到临时中,这样调用B之后,临时中就有数据了。这时,存储过程A需要先创建临时,然后调用B,B将数据插入到临时中,之后A就可以使用这些数据了。 但这样需要两个存储过程都使用相同的临时结构,可能存在耦合的问题。过,根据用户的需求,这可能是一个可行的解决方案。 现在需要构造一个示例。例如,存储过程B执行某个查询并将结果插入到临时中,存储过程A创建临时,调用B,然后从临时中读取数据。 具体步骤: 1. 在存储过程A中创建临时。 2. 调用存储过程B,该存储过程数据插入到临时。 3. 存储过程A处理临时中的数据。 示例代码可能如下: 存储过程B: CREATE PROCEDURE GetEmployeeData() BEGIN INSERT INTO temp_employees SELECT * FROM employees WHERE department = 'Sales'; END; 存储过程A: CREATE PROCEDURE ProcessData() BEGIN CREATE TEMPORARY TABLE temp_employees (...); CALL GetEmployeeData(); SELECT * FROM temp_employees; -- 或者其他处理 END; 但这里的问题是,临时需要在存储过程A中创建,并且在调用B之前存在。同时,B中的INSERT需要知道临时的结构。这可能要求两个存储过程对临时的结构有共同的了解,或者动态创建临时外,根据引用[4],临时可以在存储过程中创建,并且在同一会话中可见。因此,在存储过程A中创建临时,然后调用存储过程B,B可以直接插入数据到该临时,因为它们在同一个会话中。 但需要注意的是,临时的创建应该在调用存储过程B之前完成,否则B可能无法找到该。 所以正确的步骤应该是: 1. 在存储过程A中创建临时。 2. 调用存储过程B,B将数据插入到该临时。 3. 存储过程A处理临时中的数据。 这样,存储过程B需要知道临时是否存在,它只是执行INSERT操作。但需要确保临时的结构与INSERT的SELECT语句的结果兼容。 例如: 存储过程A: CREATE PROCEDURE MainProcedure() BEGIN -- 创建临时 CREATE TEMPORARY TABLE temp_results ( id INT, name VARCHAR(50) ); -- 调用子存储过程,子过程插入数据到临时 CALL SubProcedure(); -- 从临时中选择数据 SELECT * FROM temp_results; -- 删除临时(可选,因为会话结束自动删除) DROP TEMPORARY TABLE IF EXISTS temp_results; END; 存储过程B: CREATE PROCEDURE SubProcedure() BEGIN -- 将数据插入到临时 INSERT INTO temp_results (id, name) SELECT employee_id, employee_name FROM employees WHERE salary > 5000; END; 但这里可能存在一个问题:如果存储过程SubProcedure被单独调用,而temp_results存在,会出错。因此,可能需要确保SubProcedure只在被MainProcedure调用时使用,或者在SubProcedure中检查临时是否存在,或者创建临时的结构。 但用户的问题是如何在存储过程中调用一个存储过程并将结果插入临时,这个示例应该满足需求。需要注意的是,临时必须在调用SubProcedure之前已经创建,且结构匹配。 因此,正确的示例应该是这样的: 在存储过程A中创建临时,调用存储过程B,B将数据插入到临时中,然后存储过程A可以处理这些数据一个可能的场景是使用游标来处理存储过程的结果集。例如,存储过程B返回一个结果集,存储过程A使用游标来获取每一行并插入到临时中。但这种方法可能更复杂,因为存储过程的结果集需要被处理。 例如: 存储过程B: CREATE PROCEDURE GetData() BEGIN SELECT id, name FROM employees WHERE active = 1; END; 存储过程A: CREATE PROCEDURE ProcessData() BEGIN DECLARE done INT DEFAULT FALSE; DECLARE v_id INT; DECLARE v_name VARCHAR(100); -- 创建临时 CREATE TEMPORARY TABLE temp_data (id INT, name VARCHAR(100)); -- 声明游标 DECLARE cur CURSOR FOR CALL GetData(); -- 但MySQL中可能支持直接这样使用游标 -- 处理游标 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN cur; read_loop: LOOP FETCH cur INTO v_id, v_name; IF done THEN LEAVE read_loop; END IF; INSERT INTO temp_data VALUES (v_id, v_name); END LOOP; CLOSE cur; -- 处理临时数据 SELECT * FROM temp_data; END; 但问题在于,MySQL中可能允许在存储过程中直接通过游标获取一个存储过程的结果集。存储过程的结果集通常需要由客户端处理,而一个存储过程。因此,这种方法可能可行。 因此,更可行的方法是在被调用的存储过程中将数据直接插入到临时中,而是返回结果集。这样,主存储过程只需要创建临时的结构,调用子存储过程,子存储过程填充数据,然后主存储过程进行处理。 总结步骤: 1. 主存储过程创建临时。 2. 主存储过程调用子存储过程。 3. 子存储过程执行查询并将结果插入到临时。 4. 主存储过程使用临时中的数据进行后续操作。 示例代码应该按照这个逻辑来编写。同时,需要注意临时的创建和删除,以及错误处理。 现在需要将上述思考整理成用户友好的回答,并确保符合格式要求,如行内公式使用$...$,独立公式用$$...$$,中文回答,生成相关问题等。 同时需要引用正确的参考资料。根据用户提供的引用,引用[4]提到临时的使用,引用[3]提到存储过程的参数和结构,引用[2]涉及存储过程示例。因此,在回答中需要适当引用这些内容。 最后,生成相关问题,例如如何传递参数、如何处理多个结果集等。</think>在MySQL存储过程中调用其他存储过程并将结果存入临时,可通过以下步骤实现: ### 实现步骤 1. **创建临时** 在主存储过程中使用`CREATE TEMPORARY TABLE`定义临时结构,例如: ```sql CREATE TEMPORARY TABLE temp_employee ( id INT, name VARCHAR(50), salary DECIMAL(10,2) ); ``` 2. **调用子存储过程** 子存储过程需直接向临时插入数据。假设子存储过程`get_high_salary_employees`筛选高薪员工: ```sql CREATE PROCEDURE get_high_salary_employees() BEGIN INSERT INTO temp_employee SELECT employee_id, employee_name, salary FROM employees WHERE salary > 10000; END; ``` 3. **主存储过程整合调用** 主存储过程调用子过程后,可操作临时数据: ```sql CREATE PROCEDURE main_process() BEGIN -- 创建临时 DROP TEMPORARY TABLE IF EXISTS temp_employee; CREATE TEMPORARY TABLE temp_employee (...); -- 调用子过程填充数据 CALL get_high_salary_employees(); -- 使用临时数据(示例:统计数量) SELECT COUNT(*) FROM temp_employee; END; ``` ### 关键点 - **临时作用域**:临时仅在当前会话可见,会话结束自动删除[^4]。 - **参数传递**:若需动态筛选条件,可在子存储过程中添加`IN`参数: ```sql CREATE PROCEDURE get_employees_by_dept(IN dept_name VARCHAR(50)) BEGIN INSERT INTO temp_employee SELECT * FROM employees WHERE department = dept_name; END; ``` - **错误处理**:建议在临时操作前后添加`DROP TEMPORARY TABLE IF EXISTS`避免冲突[^3]。 ### 完整示例 ```sql -- 子存储过程:按部门筛选员工 CREATE PROCEDURE populate_temp_table(IN dept VARCHAR(50)) BEGIN INSERT INTO temp_employee SELECT id, name, salary FROM employees WHERE department = dept; END; -- 主存储过程 CREATE PROCEDURE master_procedure() BEGIN -- 创建临时 DROP TEMPORARY TABLE IF EXISTS temp_employee; CREATE TEMPORARY TABLE temp_employee ( id INT PRIMARY KEY, name VARCHAR(50), salary DECIMAL(10,2) ); -- 调用子过程插入数据 CALL populate_temp_table('Sales'); -- 使用临时数据生成报告 SELECT CONCAT(name, ' 薪资:', salary) AS report FROM temp_employee; END; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值