Informix SQL合并/加入和更新表

时间:2017-06-16 19:26:40

标签: sql informix

我有一个Informix数据库。

EMPLOYEE 
LAST_NAME  FIRST_NAME  SSN
----------------------------------------------
SMITH      JOHN        123456789                                                         
DOE        JANE        987654321                                                      
SMITH      JOHN        5555555     

SCHEDULE
SSN        START   END
---------------------------
123456789  8:00AM  4:00PM
987654321  8:00AM  4:00PM 

我需要使用ssn 5555555获取配置文件John Smith并使用ssn 123456789替换其他John Smith。此外,使用此查询我需要更新Schedule表以使用新ssn 5555555更新。

最重要的是,ssn 123456789的配置文件现已附加到ssn 5555555的日程表中。然后我需要能够使用ssn 123456789删除旧员工。

1 个答案:

答案 0 :(得分:0)

该问题的原始版本似乎讨论将9位SSN截断为7位不完全SSN。 123456789⟶5555555的修订映射不是可以通过算法完成的映射。最初的问题还讨论了处理多个映射,尽管示例数据仅显示和描述了一个。

我假设Employee表还没有John Smith的7位SSN,即使样本数据显示了。

有多种方法可以满足这些要求。这是一种方法。

为解决广义映射问题,我们可以定义一个合适的临时表,并用相关数据填充它:

CREATE TEMP TABLE SSN_map
(
    SSN_9    INTEGER NOT NULL UNIQUE,
    SSN_7    INTEGER NOT NULL UNIQUE
);
INSERT INTO SSN_map(SSN_9, SSN_7) VALUES(123456789, 5555555);
-- …

此表格可能需要是常规的'表格是否需要时间才能使其内容正确无误。这将允许多个会话正确完成映射。

如果9位和7位SSN之间存在算法映射,您仍然可以创建SSN_map表,将算法应用于SSN_9(SSN)值以创建映射。您也可以动态地应用算法'并避免映射表,但它使UPDATE语句更难以正确。

假设数据库支持事务(可以记录Informix数据库,意味着'包含事务'或者未记录,意味着没有事务'),那么:

BEGIN WORK;

-- Create 7-digit SSN entry corresponding to 9-digit SSN
INSERT INTO Employee(SSN, Last_Name, First_Name)
    SELECT m.SSN_7, e.Last_Name, e.First_Name -- , other employee columns
      FROM Employee AS e
      JOIN SSN_map  AS m ON e.SSN = m.SSN_9;

一些(较旧的)Informix版本不允许您从正在修改的表中进行SELECT,如图所示。如果这是一个问题,请使用:

SELECT m.SSN_7, e.Last_Name, e.First_Name -- , other employee columns
  FROM Employee AS e
  JOIN SSN_map  AS m ON e.SSN = m.SSN_9
  INTO TEMP mapped_emp WITH NO LOG;
INSERT INTO Employee SELECT * FROM mapped_emp;
DROP TABLE mapped_emp;

继续:Employee表现在包含每个映射员工的两个条目,一个包含旧的9位SSN,另一个包含新的7位不完全SSN。

UPDATE Schedule
   SET SSN = (SELECT SSN_7 FROM SSN_map WHERE SSN_9 = SSN)
 WHERE EXISTS(SELECT * FROM SSN_map WHERE SSN_9 = SSN);

这会使用新的非完全SSN值更新计划。 WHERE EXISTS子句用于确保只更改SSN映射表中具有条目的行。如果它不存在,任何不匹配的行都会将SSN设置为NULL,这不会很好。

DELETE FROM Employee
 WHERE SSN IN (SELECT SSN_9 FROM SSN_map);

COMMIT WORK;

这将从Employee表中删除9位SSN的旧数据。您也可以在此时删除SSN_map表。

完整的测试脚本

-- Outside the test, the Employee and Schedule tables would exist
-- and be fully loaded with data before running this script
BEGIN WORK;

CREATE TABLE EMPLOYEE 
(
    LAST_NAME   CHAR(15) NOT NULL,
    FIRST_NAME  CHAR(15) NOT NULL,
    SSN         INTEGER NOT NULL PRIMARY KEY
);

INSERT INTO Employee(Last_Name, First_Name, SSN) VALUES('SMITH', 'JOHN', 123456789);
INSERT INTO Employee(Last_name, First_Name, SSN) VALUES('DOE', 'JANE', 987654321);

CREATE TABLE SCHEDULE
(
    SSN         INTEGER NOT NULL REFERENCES Employee,
    START       DATETIME HOUR TO MINUTE NOT NULL,
    END         DATETIME HOUR TO MINUTE NOT NULL,
    PRIMARY KEY(SSN, START)
);
INSERT INTO Schedule(SSN, Start, End) VALUES(123456789, '08:00', '16:00');
INSERT INTO Schedule(SSN, Start, End) VALUES(987654321, '08:00', '16:00');

SELECT * FROM Employee;
SELECT * FROM Schedule;

-- Start the work for mapping SSN to not-quite-SSN
CREATE TEMP TABLE SSN_map
(
    SSN_9    INTEGER NOT NULL UNIQUE,
    SSN_7    INTEGER NOT NULL UNIQUE
);
INSERT INTO SSN_map(SSN_9, SSN_7) VALUES(123456789, 5555555);

-- In the production environment, this is where you'd start the transaction
--BEGIN WORK;

-- Create 7-digit SSN entry corresponding to 9-digit SSN
INSERT INTO Employee(SSN, Last_Name, First_Name)
    SELECT m.SSN_7, e.Last_Name, e.First_Name -- , other employee columns
      FROM Employee AS e
      JOIN SSN_map  AS m ON e.SSN = m.SSN_9;

UPDATE Schedule
   SET SSN = (SELECT SSN_7 FROM SSN_map WHERE SSN_9 = SSN)
 WHERE EXISTS(SELECT * FROM SSN_map WHERE SSN_9 = SSN);

DELETE FROM Employee
 WHERE SSN IN (SELECT SSN_9 FROM SSN_map);

SELECT * FROM Employee;
SELECT * FROM Schedule;

-- When satisfied, you'd use COMMIT WORK instead of ROLLBACK WORK
ROLLBACK WORK;
--COMMIT WORK;

示例输出

前四行是'之前'数据;最后四个是'之后'数据

SMITH           JOHN              123456789
DOE             JANE              987654321

  123456789 08:00 16:00
  987654321 08:00 16:00

DOE             JANE              987654321
SMITH           JOHN                5555555

    5555555 08:00 16:00
  987654321 08:00 16:00

如您所见,John Smith的材料已正确更新,但Jane Doe的材料未发生变化。鉴于Jane没有映射,这是正确的。

对于不熟悉Informix的人:是的,你真的可以在事务中包含像CREATE TABLE这样的DDL语句,是的,如果你回滚事务,创建的表确实会被回滚。并非所有DBMS都如此慷慨。