[英]Need a SQL statement focus on combination of tables but entries always with unique ID
I need SQL code to solve the tables combination problem, described on below: 我需要SQL代码来解决表组合问题,如下所述:
Table old data: table old 表旧数据:表旧
name version status lastupdate ID
A 0.1 on 6/8/2010 1
B 0.1 on 6/8/2010 2
C 0.1 on 6/8/2010 3
D 0.1 on 6/8/2010 4
E 0.1 on 6/8/2010 5
F 0.1 on 6/8/2010 6
G 0.1 on 6/8/2010 7
Table new data: table new 表新数据:表新
name version status lastupdate ID
A 0.1 on 6/18/2010
#B entry deleted
C 0.3 on 6/18/2010 #version_updated
C1 0.1 on 6/18/2010 #new_added
D 0.1 on 6/18/2010
E 0.1 off 6/18/2010 #status_updated
F 0.1 on 6/18/2010
G 0.1 on 6/18/2010
H 0.1 on 6/18/2010 #new_added
H1 0.1 on 6/18/2010 #new_added
the difference of new data and old date: 新数据和旧日期的区别:
B entry deleted B条目已删除
C entry version updated C条目版本已更新
E entry status updated E条目状态已更新
C1/H/H1 entry new added C1 / H / H1条目新添加
What I want is always keeping the ID - name mapping relationship in old data table no matter how data changed later, aka the name always has an unique ID number bind with it. 我想要的是始终保持旧数据表中的ID - 名称映射关系,无论以后数据如何更改,也就是名称始终具有绑定它的唯一ID号。
If entry has update, then update the data, if entry is new added, insert to the table then give a new assigned unique ID. 如果条目已更新,则更新数据,如果条目是新添加的,则插入表格,然后提供新分配的唯一ID。 If the entry was deleted, delete the entry and do not reuse that ID later.
如果该条目已删除,请删除该条目,稍后不要重复使用该ID。
However, I can only use SQL with simple select or update statement then it may too hard for me to write such code, then I hope someone with expertise can give direction, no details needed on the different of SQL variant, a standard sql code as sample is enough. 但是,我只能使用带有简单select或update语句的SQL,那么我可能很难编写这样的代码,那么我希望有专业知识的人可以给出方向,不需要SQL变种,标准sql代码所需的细节。样品就够了。
Thanks in advance! 提前致谢!
Rgs RGS
KC KC
======== I listed my draft sql here, but not sure if it works, some one with expertise pls comment, thanks! ========我在这里列出了我的草稿sql,但不确定它是否有效,有些专业人士请评论,谢谢!
create table tmp as select * from old 将表tmp创建为select * from old
update tmp where name in (select name from new) 更新tmp其中的名称(从新选择名称)
insert into tmp (name version status lastupdate ID) set idvar = max(select max(id) from tmp) + 1 select * from (select new.name new.version new.status new.lastupdate new.ID from old, new where old.name <> new.name) 插入到tmp(名称版本状态lastupdate ID)set idvar = max(从tmp中选择max(id))+ 1 select * from(select new.name new.version new.status new.lastupdate new.ID from old,new where old.name <> new.name)
delete from tmp where (select ???) 从tmp中删除(选择???)
Let me start from the end: 让我从头开始:
In #4 you would delete all rows in tmp; 在#4中,你将删除tmp中的所有行; what you wanted to say there is
WHERE tmp.name NOT IN (SELECT name FROM new)
; 你想说的是
WHERE tmp.name NOT IN (SELECT name FROM new)
; similarly #3 is not correct syntax, but if it was it would try to insert all rows. 同样#3语法不正确,但如果是,它会尝试插入所有行。
Regarding #2, why not use auto increment on the ID
? 关于#2,为什么不在
ID
上使用自动增量 ?
Regarding #1, if your tmp table is the same as new the queries #2-#4 make no sense, unless you change (update, insert, delete) new
table in some way. 关于#1,如果您的tmp表与新的相同,则查询#2-#4没有意义,除非您以某种方式更改(更新,插入,删除)
new
表。
But (!), if you do update the table new
and it has an auto increment field on ID
and if you are properly updating the table (using ID
) from the application then your whole procedure is unnecessary (!). 但是 (!),如果你确实更新了表
new
并且它在ID
上有一个自动增量字段,并且如果你正在从应用程序正确更新表(使用ID
)那么你的整个过程是不必要的 (!)。
So, the important thing is that you should not design the system to work like above. 所以,重要的是你不应该像上面那样设计系统。
To get the concept of updating data in the database from the application side take a look at examples here (php/mysql). 要从应用程序端获取更新数据库中数据的概念,请查看此处的示例(php / mysql)。
Also, to get the syntax correct on your queries go through the basic version of SET, INSERT, DELETE and SELECT commands (no way around this). 另外,要使查询语法正确,请通过SET,INSERT,DELETE和SELECT命令的基本版本(没有办法解决此问题)。
You never mentioned what DBMS you are using but if you are using SQL Server, one really good one is the SQL MERGE
statement. 您从未提及您正在使用的DBMS,但如果您使用的是SQL Server,那么一个非常好的是SQL
MERGE
语句。 See: http://www.mssqltips.com/tip.asp?tip=1704 请参阅: http : //www.mssqltips.com/tip.asp?tt = 1704
The MERGE statement basically works as separate insert, update, and delete statements all within the same statement.
MERGE语句基本上作为单独的insert,update和delete语句在同一语句中使用。 You specify a "Source" record set and a "Target" table, and the join between the two.
您指定“源”记录集和“目标”表,以及两者之间的连接。 You then specify the type of data modification that is to occur when the records between the two data are matched or are not matched.
然后,指定在两个数据之间的记录匹配或不匹配时要发生的数据修改类型。 MERGE is very useful, especially when it comes to loading data warehouse tables, which can be very large and require specific actions to be taken when rows are or are not present.
MERGE非常有用,特别是在加载数据仓库表时,它可能非常大并且需要在行存在或不存在时采取特定操作。
Example: 例:
MERGE Products AS TARGET
USING UpdatedProducts AS SOURCE
ON (TARGET.ProductID = SOURCE.ProductID)
--When records are matched, update
--the records if there is any change
WHEN MATCHED AND TARGET.ProductName <> SOURCE.ProductName
OR TARGET.Rate <> SOURCE.Rate THEN
UPDATE SET TARGET.ProductName = SOURCE.ProductName,
TARGET.Rate = SOURCE.Rate
--When no records are matched, insert
--the incoming records from source
--table to target table
WHEN NOT MATCHED BY TARGET THEN
INSERT (ProductID, ProductName, Rate)
VALUES (SOURCE.ProductID, SOURCE.ProductName, SOURCE.Rate)
--When there is a row that exists in target table and
--same record does not exist in source table
--then delete this record from target table
WHEN NOT MATCHED BY SOURCE THEN
DELETE
--$action specifies a column of type nvarchar(10)
--in the OUTPUT clause that returns one of three
--values for each row: 'INSERT', 'UPDATE', or 'DELETE',
--according to the action that was performed on that row
OUTPUT $action,
DELETED.ProductID AS TargetProductID,
DELETED.ProductName AS TargetProductName,
DELETED.Rate AS TargetRate,
INSERTED.ProductID AS SourceProductID,
INSERTED.ProductName AS SourceProductName,
INSERTED.Rate AS SourceRate;
SELECT @@ROWCOUNT;
GO
Note - if you are concerned about performance you can skip this whole answer :-) 注意 - 如果您担心性能,可以跳过这整个答案:-)
If you can redesign have 2 tables - one with the data and other with the name - ID linkage. 如果你可以重新设计有2个表 - 一个包含数据,另一个包含名称 - ID链接。 Something like
就像是
table_original table_original
name version status lastupdate
A 0.1 on 6/8/2010
B 0.1 on 6/8/2010
C 0.1 on 6/8/2010
D 0.1 on 6/8/2010
E 0.1 on 6/8/2010
F 0.1 on 6/8/2010
G 0.1 on 6/8/2010
and name_id 和name_id
name ID
A 1
B 2
C 3
D 4
E 5
F 6
G 7
When you get the table_new with the new set of data 当您使用新的数据集获取table_new时
Note : I think there's a bit of ambiguity about the deletion here 注意:我认为这里的删除有点含糊不清
If the entry was deleted, delete the entry and do not reuse that ID later.
如果该条目已删除,请删除该条目,稍后不要重复使用该ID。
If name A gets deleted, and it turns up again in a later set of updates do you want to a. 如果名称A被删除,并且它会在稍后的更新集中再次出现,那么你想要一个。 reuse the original ID tagged to A, or b.
重复使用标记为A或b的原始ID。 generate a new ID?
生成一个新的ID?
If it's b. 如果是b。 you need a column Deleted?
你需要删除列吗? in name_id and a last step
在name_id和最后一步
4 . 4。 set Deleted?
设置已删除? = Y where name not in table_original
= Y其中name不在table_original中
and 2. would exclude Deleted? 2.将排除已删除? = Y records.
= Y记录。
You could also do the same thing without the name_id table based on the logic that the only thing you need from table_old is the name - ID links. 你也可以在没有name_id表的情况下做同样的事情,因为你需要从table_old获得的唯一东西就是名字 - ID链接。 Everything else you need is in table_new,
你需要的其他一切都在table_new中,
This works in Informix and gives exactly the display you require. 这适用于Informix,并提供您所需的显示。 Same or similar should work in MySQL, one would think.
人们会想,相同或类似的应该在MySQL中起作用。 The trick here is to get the union of all names into a temp table and left join on that so that the values from the other two can be compared.
这里的技巧是将所有名称的并集放入临时表中并保持连接,以便可以比较其他两个的值。
SELECT DISTINCT name FROM old UNION SELECT DISTINCT name FROM new INTO TEMP _tmp; SELECT CASE WHEN b.name IS NULL THEN '' ELSE aa.name END AS name, CASE WHEN b.version IS NULL THEN '' WHEN a.version = b.version THEN a.version ELSE b.version END AS version, CASE WHEN a.status = b.status THEN a.status WHEN b.status IS NULL THEN '' ELSE b.status END AS status, CASE WHEN a.lastupdate = b.lastupdate THEN a.lastupdate WHEN b.lastupdate IS NULL THEN null ELSE b.lastupdate END AS lastupdate, CASE WHEN a.name IS NULL THEN '#new_added' WHEN b.name IS NULL THEN '#' || aa.name || ' entry deleted' WHEN a.version b.version THEN '#version_updated' WHEN a.status b.status THEN '#status_updated' ELSE '' END AS change FROM _tmp aa LEFT JOIN old a ON a.name = aa.name LEFT JOIN new b ON b.name = aa.name;
a drafted approach, I have no idea if it works fine...... 一个起草的方法,我不知道它是否正常......
CREATE TRIGGER auto_next_id AFTER INSERT ON table FOR EACH ROW BEGIN UPDATE table SET uid = max(uid) + 1 ; 创建TRIGGER auto_next_id AFTER INSERT ON表FOR FOR EACH ROW BEGIN UPDATE表SET uid = max(uid)+ 1; END;
结束;
If I understood well what you need based on the comments in the two tables, I think you can simplify a lot your problem if you don't merge or update the old table because what you need is table new with the IDs in table old when they exist and new IDs when they do not exist, right? 如果根据两个表中的注释我很清楚你需要什么,我认为如果你不合并或更新旧表,你可以简化你的问题,因为你需要的是表新的表格中的ID当它们不存在时它们存在并且有新的ID,对吧?
New records: table new has the new records already - OK (but they need a new ID) Deleted Records: they are not in table new - OK Updated Records: already updated in table new - OK (need to copy ID from table old) Unmodified records: already in table new - OK (need to copy ID from table old) 新记录:表new已经有了新记录 - OK(但是他们需要一个新ID)删除记录:它们不在表中新 - OK更新记录:已在表new中更新 - OK(需要从表old中复制ID)未修改的记录:已在表中新建 - 确定(需要从旧表中复制ID)
So the only thing you need to do is to: (a) copy the IDs from table old to table new when they exist (b) create new IDs in table new when they do not exist in table old (c) copy table new to table old. 因此,您唯一需要做的是:(a)将表旧的ID复制到表new(b)在表new(c)复制表new中不存在时,在表new中创建新的ID桌子老。
(a) UPDATE new SET ID = IFNULL((SELECT ID FROM old WHERE new.name = old.name),0); (a)UPDATE new SET ID = IFNULL((SELECT ID FROM old WHERE new.name = old.name),0);
(b) UPDATE new SET ID = FUNCTION_TO GENERATE_ID(new.name) WHERE ID = 0; (b)更新新的SET ID = FUNCTION_TO GENERATE_ID(new.name)WHERE ID = 0;
(c) Drop table old; (c)旧桌子; CREATE TABLE old (select * from new);
CREATE TABLE old(select * from new);
As I don't know which SQL database you are using, in (b) you can use an sql function to generate the unique id depending on the database. 由于我不知道您正在使用哪个SQL数据库,因此在(b)中您可以使用sql函数根据数据库生成唯一ID。 With SQL Server, newid(), With postgresql (not too old versions), now() seems a good choice as its precision looks sufficient (but not in other databases as MySQL for example as I think the precision is limited to seconds)
使用SQL Server,newid(),使用postgresql(不是太旧的版本),now()似乎是一个不错的选择,因为它的精度看起来足够(但在其他数据库中不像MySQL那样我认为精度仅限于秒)
Edit: Sorry, I hadn't seen you're using sqlite and python. 编辑:对不起,我没有看到你正在使用sqlite和python。 In this case you can use str(uuid.uuid4()) function (uuid module) in python to generate the uuid and fill the ID in new table where ID = 0 in step (b).
在这种情况下,您可以在python中使用str(uuid.uuid4())函数(uuid模块)生成uuid并在步骤(b)中填充ID为0的新表中的ID。 This way you'll be able to join 2 independent databases if needed without conflicts on the IDs.
这样,如果需要,您将能够加入2个独立的数据库而不会出现ID冲突。
Why don't you use a UUID for this? 为什么不为此使用UUID? Generate it once for a plug-in, and incorporate/keep it into the plug-in, not into the DB.
为插件生成一次,并将其保存到插件中,而不是插入到数据库中。 Now that you mention python, here's how to generate it:
现在您提到python,以下是如何生成它:
import uuid
UID = str(uuid.uuid4()) # this will yield new UUID string
Sure it does not guarantee global uniqueness, but chances you get the same string in your project is pretty low. 当然它不能保证全局唯一性,但是你在项目中获得相同字符串的可能性非常低。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.