简体   繁体   English

如何在 SQL 服务器表中插入

[英]How to do this insert in a SQL Server table

I want to insert data into table tabA.我想将数据插入表tabA。 I get this error我收到这个错误

Violation of UNIQUE KEY constraint, Cannot insert duplicate key in object.违反 UNIQUE KEY 约束,无法在 object 中插入重复键。

The key is ( no_command, no_document, id_transc, project_cd ).关键是( no_command, no_document, id_transc, project_cd )。

Here is a sample of data to insert:这是要插入的数据示例:

load_number | load_date | no_command | no_document | id_transc | div1 | div2 | activity_cd | project_cd
1             2021-04-10   38                          -1         0     200                  1
1             2021-04-10   38                          -1         600    0                   1

It's not the same data because div1 and div2 are different.这不是相同的数据,因为 div1 和 div2 不同。 I did a group by to solve the problem but it doesn't work.我做了一个小组来解决问题,但它不起作用。 I have this error in the group by.我在 group by 中有这个错误。

Invalid column name列名无效

Here is my code这是我的代码

INSERT INTO tabA ([load_number], [load_date], [no_command], [no_document],
                  [id_transc], [div1], [div2], [activity_cd], [project_cd])
    SELECT 
        1 [load_number], GETDATE() [load_date], id_cmd [no_command], '' [no_document],
        COALESCE(c.id_numb, -1) [id_transc],
        CASE
            WHEN b.data_type = 'primary' THEN b.amount
            ELSE 0
        END as [div1],
        CASE
            WHEN b.data_type = 'secondary' THEN b.amount
            ELSE 0
        END as [div2],
        COALESCE(d.budget_cd, -1) [activity_cd], code [project_cd]
    FROM
        tabB b
    LEFT JOIN 
        tabC c ON c.credit = b.account
    LEFT JOIN 
        tabD d ON d.activity = SUBSTRING([b.name], CHARINDEX('-', [b.name]) + 1, LEN([b.name])) 
               AND d.transc = '1010'
     GROUP BY
         [load_number], [load_date], [no_command], [no_document],
         [id_transc], [activity_cd], [project_cd]

I was not the one who designed the database and I cannot make changes to it.我不是设计数据库的人,我无法对其进行更改。

Need help please...需要帮助请...

You can add a where clause with not exists :您可以添加not existswhere子句:

where not exists (select 1
                  from tabA a
                  where a.no_command = ?.id_cmd and
                        a.no_document = '' and
                        a.id_transc = coalesce(c.id_numb,-1) and
                        a.project_cd = ?.code
                 )

The ? ? are for the table aliases to define where the columns come from.用于表别名来定义列的来源。 As a best practice, you should qualify all column references in all your queries.作为最佳实践,您应该限定所有查询中的所有列引用。 This is particularly important when using correlated subqueries.这在使用相关子查询时尤其重要。

(writing here as it would be a mess). (写在这里会很乱)。 Assuming that output is right and you simply want to aggregate those rows:假设 output 是正确的,并且您只想聚合这些行:

WITH
  myData AS (
              SELECT
                       id_cmd                                                          [no_command]
                     , COALESCE(c.id_numb, -1)                                         [id_transc]
                     , SUM(CASE WHEN b.data_type='primary' THEN b.amount ELSE 0 END)   AS [div1]
                     , SUM(CASE WHEN b.data_type='secondary' THEN b.amount ELSE 0 END) AS [div2]
                     , COALESCE(d.budget_cd, -1)                                       [activity_cd]
                     , code                                                            [project_cd]
              FROM     tabB           b
                       LEFT JOIN tabC c ON c.credit=b.account
                       LEFT JOIN tabD d ON d.activity=SUBSTRING(
                                                           [b.name], CHARINDEX('-', [b.name])+1
                                                           , LEN([b.name])
                                                           )
                                       AND d.transc='1010'
              GROUP BY id_cmd, COALESCE(c.id_numb, -1), COALESCE(d.budget_cd, -1), [code]
            )
INSERT INTO tabA([load_number], [load_date], [no_command], [no_document], [id_transc], [div1]
               , [div2], [activity_cd], [project_cd])
SELECT
     1, GETDATE(), [no_command], '', [id_transc], [div1], [div2], [activity_cd], [project_cd]
FROM myData;

Please note that an aggregation like SUM() might be questionable when there are joins.请注意,当有连接时,像 SUM() 这样的聚合可能会产生问题。 If those joins are meant to be 1-to-Many then it is OK, else be careful and do the summing of tabB separately before the joins.如果这些连接是一对多的,那么没关系,否则要小心,并在连接之前分别对 tabB 求和。

The shared code errors because the data violates the primary key of the table into which you are trying to insert it.共享代码错误,因为数据违反了您尝试将其插入的表的主键。 You have two records which while not duplicates of each other (they have different values for Div1 and Div2 as you say), they do share the same values for all the primary key fields.您有两条记录,虽然彼此不重复(如您所说,它们对Div1Div2具有不同的值),但它们确实为所有主键字段共享相同的值。 So either所以要么

  1. The table needs changing to allow these two rows, or该表需要更改以允许这两行,或者
  2. One or both of these rows should be rejected, or这些行中的一个或两个应该被拒绝,或者
  3. The the two rows should somehow be collapsed into a single row这两行应该以某种方式折叠成一行

I'm guessing the third option is correct and that the way to do this is to SUM the values which are returned in Div1 and Div2 .我猜第三个选项是正确的,这样做的方法是将SUMDiv2返回的值Div1 Below is my best guess as to what you want:以下是我对您想要什么的最佳猜测:

SELECT
   1 [load_number],
   GETDATE() [load_date],
   id_cmd [no_command],
   '' [no_document],
   COALESCE(c.id_numb, -1) [id_transc],
   SUM(CASE WHEN b.data_type = 'primary' THEN b.amount ELSE 0 END) as [div1],
   SUM(CASE WHEN b.data_type = 'secondary' THEN b.amount ELSE 0 END) as [div2],
   COALESCE(d.budget_cd, -1) [activity_cd],
   code [project_cd]
FROM
   tabB b
   LEFT JOIN tabC c ON c.credit = b.account
   LEFT JOIN tabD d ON d.activity = SUBSTRING([b.name], CHARINDEX('-', [b.name]) + 1, LEN([b.name])) AND d.transc = '1010'
GROUP BY
   --Each of the things selected (which aren't static, getdate is static for these purposes) but aren't within aggregate functions appears below.
   --Note that they are not referenced by the alias given in the select clause.
   id_cmd,
   COALESCE(c.id_numb, -1),
   COALESCE(d.budget_cd, -1),
   code

It's hard to tell without knowing the your data, but even when doing this it looks like you could run into issues.在不知道您的数据的情况下很难判断,但即使这样做,您也可能会遇到问题。 This is because we are grouping by fields which aren't part of your primary key for the table, namely the [activity_cd] field (or COALESCE(d.budget_cd,-1) ).这是因为我们按不属于表主键的字段进行分组,即[activity_cd]字段(或COALESCE(d.budget_cd,-1) )。 If it's possible for two records to agree in the primary key fields while differing in this one, then such data would result in errors similar to those you've encountered already.如果两条记录可能在主键字段中一致,而在这条记录中不同,则此类数据将导致与您已经遇到的错误类似的错误。

As GordonLinoff mentions, it is good practice to give make sure that you fully qualify the fields which are referenced in the query.正如 GordonLinoff 所提到的,确保您完全限定查询中引用的字段是一种很好的做法。 You've done this in places ( c.id_numb ) but not others ( id_cmd ).您已经在某些地方( c.id_numb )而不是其他地方( id_cmd )做到了这一点。 This helps make code easier to understand and may prevent the code producing errors in the event of changes to table schemas causing field names to become ambiguous.这有助于使代码更易于理解,并且可以防止代码在更改表模式导致字段名称变得模糊的情况下产生错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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