我有这个没有主键的表。
我将在一个新表中插入一些记录来分析它们,我正在考虑用所有可用列的值创建一个新的主键。
如果这是像Java这样的编程语言,我会:
int hash = column1 * 31 + column2 * 31 + column3*31
或类似的东西。但这是SQL。
如何根据可用列的值创建主键?简单地将所有列标记为PK对我来说不起作用,因为我需要做的是将它们与来自其他DB表的数据进行比较。
我的桌子上有3个号码和一个日期。
编辑我的问题是什么
我认为需要更多背景知识。我很抱歉没有提供它。
我有一个数据库(dm),每天从另一个db(原始源)更新。它有过去两年的记录。
上个月(7月)更新过程中断,一个月内没有数据更新到dm。
我在Oracle XE中手动创建一个具有相同结构的表,然后将原始源中的记录复制到我的db(myxe)中,我从7月份仅复制了记录,以创建月末所需的报告。
最后在8月8日,更新过程得到修复,并且等待通过此自动过程迁移的记录被复制到数据库中(从originalsource到dm)。
此过程会在复制数据(到dm)后从原始源清除数据。
一切看起来都不错,但我们刚刚意识到有一些记录丢失了(约占7月份的25%)
所以,我想要做的是使用我的备份(myxe)并将所有缺失的记录插入数据库(dm)。
这里的问题是:
所以我想如果我可以从两个表创建一个唯一的pk,它给出了相同的数字,我可以分辨出哪些丢失并插入它们。
编辑2
所以我在当地环境中做了以下事情:
select a.* from the_table@PRODUCTION a , the_table b where
a.idle = b.idle and
a.activity = b.activity and
a.finishdate = b.finishdate
返回两个数据库中存在的所有行(... union?)我有2000条记录。
接下来要做的是从目标数据库中删除它们,然后将它们从我的数据库中的所有内容插入到目标表中
我希望我没有陷入最糟糕的事情: - S:-S
答案 0 :(得分:3)
只需创建一个代理键:
ALTER TABLE mytable ADD pk_col INT
UPDATE mytable
SET pk_col = rownum
ALTER TABLE mytable MODIFY pk_col INT NOT NULL
ALTER TABLE mytable ADD CONSTRAINT pk_mytable_pk_col PRIMARY KEY (pk_col)
或者这个:
ALTER TABLE mytable ADD pk_col RAW(16)
UPDATE mytable
SET pk_col = SYS_GUID()
ALTER TABLE mytable MODIFY pk_col RAW(16) NOT NULL
ALTER TABLE mytable ADD CONSTRAINT pk_mytable_pk_col PRIMARY KEY (pk_col)
后者使用GUID
,它们在数据库中是唯一的,但占用的空间更多,生成速度要慢得多(INSERT
的速度会很慢)
<强>更新强>
如果您需要在具有相同数据的两个表上创建相同的PRIMARY KEY
,请使用以下命令:
MERGE
INTO mytable v
USING (
SELECT rowid AS rid, rownum AS rn
FROM mytable
ORDER BY
co1l, col2, col3
)
ON (v.rowid = rid)
WHEN MATCHED THEN
UPDATE
SET pk_col = rn
请注意,表格应该相同,直到一行(即具有相同数量的行,其中包含相同的数据)。
Update 2
:
对于您的问题,您根本不需要PK
。
如果您只想选择dm
中缺少的记录,请使用此记录(在dm
侧)
SELECT *
FROM mytable@myxe
MINUS
SELECT *
FROM mytable
这将返回mytable@myxe
但不在mytable@dm
请注意,如果有的话,它会缩小所有重复项。
答案 1 :(得分:3)
通过组合3个数字和日期来创建哈希值的危险在于它可能不是唯一的,因此不能安全地用作主键。
相反,我建议您为主键使用自动增量ID。
答案 2 :(得分:1)
假设您确保了唯一性......您可以在SQL中执行几乎相同的操作。唯一的问题是将日期转换为数值,以便您可以对其进行哈希处理。
Select Table2.SomeFields
FROM Table1 LEFT OUTER JOIN Table2 ON
(Table1.col1 * 31) + (Table1.col2 * 31) + (Table1.col3 * 31) +
((DatePart(year,Table1.date) + DatePart(month,Table1.date) + DatePart(day,Table1.date) )* 31) = Table2.hashedPk
上述查询适用于SQL Server,Oracle的唯一区别在于您处理日期转换的方式。此外,还有其他功能用于在SQL Server中转换日期,因此这绝不是唯一的解决方案。
并且,您可以将此与Quassnoi的SET语句结合使用以填充新字段。只需使用Join条件逻辑的左侧作为值。
答案 3 :(得分:1)
如果您使用旧表中的值加载新表,然后需要加入这两个表,则只有在能够唯一标识原始表中的每一行时才能“正确”执行此操作。 Quassnoi的解决方案将允许您执行此操作,如果您可以通过添加新列来更改旧表。
如果您无法更改原始表,则可以使用基于旧表的列生成某种形式的哈希代码 - 但是,仅当哈希码唯一标识每一行时才会生效。 (Oracle有校验和功能,对吗?如果有,请使用它们。)
如果无法保证哈希码唯一性,则可能必须满足由确保唯一性所需的多列组成的主键(例如,自然键)。如果没有自然键,那么,我曾经听说Oracle为每行数据提供了一个rownum,你可以使用它吗?