我有一个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删除旧员工。
答案 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都如此慷慨。