Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何在准唯一数据键上创建主键?_Sql_Sql Server_Tsql_Ssis - Fatal编程技术网

Sql 如何在准唯一数据键上创建主键?

Sql 如何在准唯一数据键上创建主键?,sql,sql-server,tsql,ssis,Sql,Sql Server,Tsql,Ssis,我有一个每晚的SSIS进程,它从AS400数据库系统导出大量数据。由于AS400 DB软件中存在缺陷,在数据表中插入了专用的重复键。每次向AS400表中添加一个新的副本,都会终止我的夜间导出过程。这个问题已经从令人讨厌变成了一个问题 我需要的是有一个只插入唯一数据的选项。如果存在重复行,请选择重复行中遇到的第一行。有没有SQL语法可以帮助我做到这一点?我知道DISTINCT ROW子句,但这在我的情况下不起作用,因为对于大多数有问题的记录,除了组成PK的字段之外,所有数据都是非唯一的 在我的例子

我有一个每晚的SSIS进程,它从AS400数据库系统导出大量数据。由于AS400 DB软件中存在缺陷,在数据表中插入了专用的重复键。每次向AS400表中添加一个新的副本,都会终止我的夜间导出过程。这个问题已经从令人讨厌变成了一个问题

我需要的是有一个只插入唯一数据的选项。如果存在重复行,请选择重复行中遇到的第一行。有没有SQL语法可以帮助我做到这一点?我知道DISTINCT ROW子句,但这在我的情况下不起作用,因为对于大多数有问题的记录,除了组成PK的字段之外,所有数据都是非唯一的

在我的例子中,主键在SQL Server DB缓存中保持唯一性比拥有完整的数据快照更重要。我可以做些什么来强制SSIS/SQL Server中的导出受此约束,而不会导致进程崩溃

编辑

让我进一步澄清我的要求。我需要的是确保导出的SQL Server表中的数据维护的键与AS400数据表中维护的键相同。换句话说,创建唯一的行计数标识符是行不通的,插入所有没有主键的数据也是行不通的

如果AS400软件中的一个错误允许错误的、重复的PK,我想忽略这些行,或者,最好只选择一个具有重复键的行,而不是两个

此SELECT语句可能来自我的SSIS项目中的SELECT语句,该项目通过ODBC连接连接到大型机


我怀疑我的问题可能没有“简单”的解决办法。然而,我希望我错了。

SQLServer2005
及以上版本中:

SELECT  *
FROM    (
        SELECT  *,
                ROW_NUMBER() OVER (PARTITION BY almost_unique_field ORDER BY id) rn
        FROM    import_table
        ) q
WHERE   rn = 1

由于您使用的是SSI,因此必须使用
OLE DB Source
从AS400获取数据,并且必须使用
OLE DB Destination
将数据插入SQL Server

让我们假设您没有任何转换

在OLE DB源之后添加
排序转换。在排序转换中,底部有一个复选框选项,用于根据给定的列值集删除重复的行。检查所有字段,但不要选择来自AS400的主键。这将消除重复的行,但将插入您仍然需要的数据


我希望这就是你想要的。

有几种选择

如果使用忽略重复键(http://www.sqlservernation.com/home/creating-indexes-with-ignore_dup_key.html)选项,SQL将发出警告,只有重复记录才会失败

您还可以对数据进行分组/汇总,但这可能会非常昂贵。我的意思是:

SELECT Id, MAX(value1), MAX(value2), MAX(value3) etc
另一个选项是向临时表中添加一个标识列(并在该列上添加集群,以便以后高效连接),然后在临时表中创建映射。映射表将是:

CREATE TABLE #mapping 
( 
    RowID INT PRIMARY KEY CLUSTERED,
    PKIN INT
)

INSERT INTO #mapping
SELECT PKID, MIN(rowid) FROM staging_table  
GROUP BY PKID

INSERT INTO presentation_table
SELECT S.* 
FROM Staging_table S 
    INNER JOIN #mapping M 
        ON S.RowID = M.RowID 

如果我理解正确,您已经复制了在其他字段中具有不同数据的PK

首先,将另一个数据库中的数据放入临时表中。如果我这样做的话,我发现研究导入(特别是大型导入)的问题更容易。实际上,我使用了两个暂存表(对于本例,我强烈建议使用),一个包含原始数据,另一个仅包含我打算导入系统的数据

现在,您可以使用并执行SQL任务来获取每个键的一条记录(请参阅@Quassnoi了解如何根据您的情况调整他的查询)。就我个人而言,我将一个标识放在我的暂存表中,这样我就可以识别重复数据的第一次或最后一次出现。然后将为每个键选择的记录放入第二个暂存表中。如果您使用的是异常表,请复制未移动到该表的记录,并且不要忘记异常的原因码(例如“复制键”)

现在,在暂存表中每个键只有一条记录,接下来的任务是决定如何处理其他非唯一数据。如果同一客户有两个不同的业务地址,您会选择哪一个?这是一个业务规则定义的问题,而不是严格意义上的SSI或SQL代码。当数据需要在两个记录之间合并时,您必须定义如何选择数据的业务规则(您所做的工作相当于重复数据消除过程)。如果幸运的话,可以使用日期字段或其他方法来确定最新或最旧的数据,以及他们希望您使用的数据。在这种情况下,只要选择一条记录,就可以完成初始转换

更可能的是,您可能需要为每个字段使用不同的规则来选择正确的规则。在这种情况下,您可以在数据流或Exec SQl任务中写入SSIS转换,以选择正确的数据并更新临时表


一旦获得了要导入的确切记录,然后执行数据流以移动到正确的生产表

我可能需要修改我的问题,但这不是我的意思。我想说的是,如果一个字段应该是唯一的,但不是唯一的,有没有办法获取一些数据?是的,可以添加行号。但我需要的是找到一种方法,在SQL Server中为我的unique、PKs unique设置密钥,即使它们在原始数据库中不是唯一的。@RLH:请发布一些您希望看到的示例输入和输出数据。这可以在SSIS中的执行SQL任务中使用。我总是将我的原始数据放入一个临时表中,然后在设置转换之前,我会执行类似的任务。您还可以将复制的记录移动到异常表中,以便稍后检查不同的数据,以查看导入的数据是否需要更改或用于发送回异常表