restartJJ 2019-10-18 19:09 采纳率: 0%
浏览 495

1、用户表(用户编号,用户名称, 性别 ,出身日期, 身份证号,所属部门编号,所属职位编号,是否管理员[bool]) 2、部门表(部门编号,部门名称) 3、用户工资表(用户编号,工资月份,工资金额)

3、写sql语句,往用户表中插入10条数据(出身日期空着,不要插入数据,其他字段自己插入) 4、写sql语句,获取身份证号中的出身年月,更新到出身日期字段 5、写sql语句,插入数据到工资表(每个用户,分别插入1、2、3月份的工资数据) 6、写储存过程,执行以下操作(存储过程,要加事务,保持数据的一致性) 用游标执行以下操作(一定要用游标操作) 如果用户是管理员,2月份工资增加10元 返回数据: 用户编号 用户姓名 性别 出身日期 身份证号 所属部门名称 是否管理员 工资明细 要求如下: 工资明细格式如下 (1月300元,2月500元,3月300元)

第6步的存储过程如何用游标操作,怎么保持数据的一致性?

  • 写回答

1条回答 默认 最新

  • $encoding 2023-03-24 16:21
    关注

    以上是三张关系表的表结构,其中:

    1. 用户表包括用户编号、用户名称、性别、出身日期、身份证号、所属部门编号、所属职位编号、是否管理员等字段信息,可用于存储用户基本信息和权限控制等;
    2. 部门表包括部门编号和部门名称两个字段,可用于存储部门的基本信息;
    3. 用户工资表包括用户编号、工资月份和工资金额三个字段,可用于存储每个用户各个月份的工资信息。

    这三张表可以建立外键约束,使得用户表和用户工资表之间、部门表和用户表之间有关联关系,以便进行更加灵活的查询和分析。

    1. 往用户表中插入10条数据的SQL语句:
    INSERT INTO 用户表 (用户编号, 用户名称, 性别, 身份证号, 所属部门编号, 所属职位编号, 是否管理员)
    VALUES
    (1, '张三', '男', '310101199001010001', 1, 1, 0),
    (2, '李四', '女', '310101199102020002', 2, 2, 0),
    (3, '王五', '男', '310101198903030003', 3, 3, 1),
    (4, '赵六', '女', '310101199004040004', 4, 4, 1),
    (5, '周七', '男', '310101199205050005', 5, 5, 0),
    (6, '钱八', '女', '310101199306060006', 6, 6, 0),
    (7, '孙九', '男', '310101199407070007', 7, 7, 0),
    (8, '吴十', '女', '310101199508080008', 8, 8, 0),
    (9, '郑十一', '男', '310101199606090009', 9, 9, 0),
    (10, '陈十二', '女', '310101199707100010', 10, 10, 0);
    
    1. 获取身份证号中的出身年月,更新到出身日期字段的SQL语句:
    UPDATE 用户表
    SET 出身日期 = STR_TO_DATE(SUBSTR(身份证号, 7, 8), '%Y%m%d');
    
    1. 插入数据到工资表(每个用户,分别插入1、2、3月份的工资数据)的SQL语句:
    INSERT INTO 用户工资表 (用户编号, 工资月份, 工资金额)
    SELECT 用户编号, '2020-01-01', RAND()*10000+5000 FROM 用户表;
    
    INSERT INTO 用户工资表 (用户编号, 工资月份, 工资金额)
    SELECT 用户编号, '2020-02-01', RAND()*10000+5000 FROM 用户表;
    
    INSERT INTO 用户工资表 (用户编号, 工资月份, 工资金额)
    SELECT 用户编号, '2020-03-01', RAND()*10000+5000 FROM 用户表;
    

    其中,RAND() 函数用于生成随机数,加上一个基准值 5000,确保生成的工资金额在 5000 到 15000 之间。

    1. 编写储存过程的SQL语句:
    CREATE PROCEDURE 查询用户工资(IN p_user_id INT, IN p_salary_month VARCHAR(7))
    BEGIN
        SELECT *
        FROM 用户工资表
        WHERE 用户编号 = p_user_id AND 工资月份 = p_salary_month;
    END;
    

    该储存过程用于查询指定用户在指定工资月份的工资信息。其中,IN 参数 p_user_id 和 p_salary_month 分别表示用户编号和工资月份,使用时需要传入参数值。

    执行以下操作(存储过程,要加事务,保持数据的一致性):

    DELIMITER //
    CREATE PROCEDURE 更新用户工资(IN p_user_id INT, IN p_salary_month VARCHAR(7), IN p_salary_amount DECIMAL(10, 2))
    BEGIN
        DECLARE exit handler for sqlexception
        BEGIN
            ROLLBACK;
            RESIGNAL;
        END;
        
        START TRANSACTION;
        UPDATE 用户工资表
        SET 工资金额 = p_salary_amount
        WHERE 用户编号 = p_user_id AND 工资月份 = p_salary_month;
        COMMIT;
    END//
    DELIMITER ;
    

    该存储过程用于更新指定用户在指定月份的工资金额。其中,IN 参数 p_user_id、p_salary_month 和 p_salary_amount 分别表示用户编号、工资月份和新的工资金额,使用时需要传入参数值。为了保障数据的一致性,该存储过程使用了事务来包装更新操作,同时使用了异常处理器进行回滚。

    用游标执行以下操作(一定要用游标操作):

    DECLARE cur CURSOR FOR
    SELECT 用户编号, 是否管理员
    FROM 用户表;
        
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET @done = true;
    
    OPEN cur;
    
    label1: LOOP
        FETCH cur INTO @user_id, @is_admin;
        IF @done THEN 
            LEAVE label1; 
        END IF;
        
        IF @is_admin THEN
            -- Do something for admin user
            SELECT CONCAT('User ', @user_id, ' is an admin user.') AS info;
        END IF;
    END LOOP;
    
    CLOSE cur;
    

    该代码使用游标来遍历用户表,并通过判断是否管理员的字段值,对不同类型的用户进行不同的操作。在本例中,如果用户是管理员,就输出一条提示信息,告知该用户是管理员用户。

    请注意,使用游标操作可能会影响查询性能,应该尽量避免使用游标操作,除非必要。

    以下是根据题目要求编写的SQL语句:

    UPDATE 用户工资表
    SET 工资金额 = 工资金额 + 10
    WHERE 工资月份 = '2020-02-01';
    
    SELECT 
      u.用户编号, 
      u.用户名称, 
      u.性别, 
      u.出身日期, 
      u.身份证号, 
      d.部门名称, 
      u.是否管理员, 
      CONCAT(
        '1月', 
        (SELECT 工资金额 FROM 用户工资表 WHERE 用户编号 = u.用户编号 AND 工资月份 = '2020-01-01'),
        '元, ',
        '2月', 
        (SELECT 工资金额 FROM 用户工资表 WHERE 用户编号 = u.用户编号 AND 工资月份 = '2020-02-01'),
        '元, ',
        '3月', 
        (SELECT 工资金额 FROM 用户工资表 WHERE 用户编号 = u.用户编号 AND 工资月份 = '2020-03-01'),
        '元'
      ) AS 工资明细
    FROM 
      用户表 AS u 
      JOIN 部门表 AS d ON u.所属部门编号 = d.部门编号;
    

    该代码首先更新了工资月份为 2020-02-01 的工资金额,将其增加 10 元,然后查询用户表和部门表联表,并使用子查询和 CONCAT 函数生成了工资明细的字符串。最终的查询结果包括了所有用户的编号、姓名、性别、出生日期、身份证号、所属部门名称、是否管理员和工资明细等信息。

    以下是使用游标操作实现第6步存储过程的示例代码:

    DELIMITER //
    
    CREATE PROCEDURE 查询用户工资(IN p_user_id INT, IN p_salary_month VARCHAR(7))
    BEGIN
        DECLARE exit handler for sqlexception
        BEGIN
            ROLLBACK;
            RESIGNAL;
        END;
        
        DECLARE done INT DEFAULT false;
        DECLARE cur CURSOR FOR
        SELECT 用户编号, 工资金额
        FROM 用户工资表
        WHERE 用户编号 = p_user_id AND 工资月份 = p_salary_month
        FOR UPDATE; --使用FOR UPDATE语句锁定查询结果,避免并发更新同一条记录出现数据不一致的情况
        
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = true;
        
        START TRANSACTION;
        
        OPEN cur;
        
        label1: LOOP
            FETCH cur INTO @user_id, @salary_amount;
            
            IF done THEN 
                LEAVE label1; 
            END IF;
            
            -- Do some calculations based on @salary_amount
            
            UPDATE 用户工资表
            SET 工资金额 = @salary_amount -- 修改工资金额
            WHERE 用户编号 = p_user_id AND 工资月份 = p_salary_month;
        END LOOP;
        
        CLOSE cur;
        
        COMMIT;
    END//
    
    DELIMITER ;
    

    该存储过程使用游标遍历了符合条件的工资记录,并使用 FOR UPDATE 语句锁定了查询结果,以避免多个会话同时更新同一个工资记录导致数据不一致的问题。然后,根据需要做一些计算,最后更新符合条件的工资记录的工资金额字段。在更新之前,使用了事务来包装整体操作,确保数据的一致性。

    评论

报告相同问题?

悬赏问题

  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)
  • ¥15 AIC3204的示例代码有吗,想用AIC3204测量血氧,找不到相关的代码。