生成唯一的外键元组

时间:2012-08-17 14:49:51

标签: sql tsql sql-server-2008-r2

我有一张这样的表:

CREATE Table tblClassProperty (
    ClassPropertyID integer IDENTITY(1,1) PRIMARY KEY,
    Active bit DEFAULT 0 NOT NULL,
    DEL bit DEFAULT 0 NOT NULL,
    FINAL bit DEFAULT 0 NOT NULL,
    Locked bit DEFAULT 0 NOT NULL,
    _Project integer FOREIGN KEY REFERENCES tblProject(ProjectID),
    _Property integer FOREIGN KEY REFERENCES tblProperty(PropertyID),
    _Class integer FOREIGN KEY REFERENCES tblClass(ClassID)
    CONSTRAINT CClassProperty UNIQUE(_Project,_Property,_Class))

我正在将旧表(在另一个数据库中)中的数据迁移到此表中。对于大多数列,我只是从另一个表复制数据。旧数据库中不存在外键列,它们只是与新数据库中相应表链接的随机值。对于您的解决方案,请理所当然地认为列_Project,_Property和_Class的值需要按照它们现在的方式生成(使用SELECT TOP 1 ...

INSERT INTO ClassDB..tblClassProperty (Active, DEL, FINAL, Locked, 
    _Project, _Property, _Class)
SELECT Active, DEL, FINAL, Locked, 
    (SELECT TOP 1 ProjectID FROM ClassDB..tblProject ORDER BY NEWID()),
    (SELECT TOP 1 PropertyID FROM ClassDB..tblProperty ORDER BY NEWID()),
    (SELECT TOP 1 ClassID FROM ClassDB..tblClass ORDER BY NEWID()),
FROM ClassDB_Access..tblClassProperty

现在,由于唯一约束,INSERT INTO脚本不会运行,并且约束必须保持不变。

我的问题:我需要一个复制现有列的脚本,如上所述生成外键,但生成的元组值(_Project, _Property, _Class)将根据约束条件是唯一的。

脚本必须在SQL Server 2008 R2中运行,并且将来也在Oracle中运行。

1 个答案:

答案 0 :(得分:0)

您可以交叉连接所有三列,为它们分配随机行号并将它们连接回由row_number增强的tblClassproperty:

; with randomized as (
   select a.ProjectID,
          b.PropertyID,
          c.ClassID,
          row_number() over(order by newid()) rn
     from ClassDB..tblProject a
    cross join ClassDB..tblProperty b
    cross join ClassDB..tblClass c
),
ordered as (
   select Active, DEL, FINAL, Locked,
          row_number() over (order by newid()) rn
     from ClassDB_Access..tblClassProperty
)
INSERT INTO ClassDB..tblClassProperty (Active, DEL, FINAL, Locked, 
    _Project, _Property, _Class)
select ordered.Active, ordered.DEL, ordered.FINAL, ordered.Locked, 
       randomized.projectID, randomized.PropertyID, randomized.ClassID
  from ordered
 inner join randomized
    on ordered.rn = randomized.rn

如果不重新调整cte部分,这在Oracle中不起作用 - 或者您可以使用派生表重写它以实现即时兼容性。

免责声明:除语法检查外,未经测试。表现可能很糟糕。

修改:忘记提及,如果ID中有重复值,您可能希望在交叉连接之前做不同的事。