简体   繁体   English

需要SQL语句专注于表的组合,但条目始终具有唯一ID

[英]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,但不确定它是否有效,有些专业人士请评论,谢谢!

1.duplicate old table as tmp for store updates 1.将旧表作为tmp用于商店更新

create table tmp as select * from old 将表tmp创建为select * from old

2.update into tmp where the "name" is same in old and new table 2.更新到tmp,其中“name”在旧表和新表中相同

update tmp where name in (select name from new) 更新tmp其中的名称(从新选择名称)

3.insert different "name" (old vs new) into tmp and assign new ID 3.将不同的“名称”(旧的与新的)插入tmp并分配新的ID

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)

4. delete the deleted entries from tmp table (such as B) 4.从tmp表中删除已删除的条目(例如B)

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时

  1. TRUNCATE table_original TRUNCATE table_original
  2. INSERT INTO name_id (names from table_new not in name_id) INSERT INTO name_id(table_new中的名称不在name_id中)
  3. copy table_new to table_original 将table_new复制到table_original

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM