【问题标题】:Insert on a child table and update FK on parent在子表上插入并在父表上更新 FK
【发布时间】:2019-10-16 03:16:13
【问题描述】:

我有一个具有以下结构和数据的父表:

---------------------------------------------
|  Id | TranslationId |                Name |
---------------------------------------------
|   1 |          NULL |          Image1.jpg |
|   2 |          NULL |          Image7.jpg |
|   3 |          NULL |    Picture_Test.png |
---------------------------------------------

还有保存翻译图像的空子表:

-------------------------------------------------------------------------
|  Id |                  De |                  Fr |                  En |
-------------------------------------------------------------------------
|     |                     |                     |                     |
-------------------------------------------------------------------------

现在我正在寻找一个查询语句或至少几个无需任何进一步编程即可运行的查询。使用脚本或编程来完成这项工作很容易,但我经常遇到需要这种插入/更新的情况。而且每次都开发一个小型控制台应用程序是不可行的。

最后两张表应该是这样的:

---------------------------------------------
|  Id | TranslationId |                Name |
---------------------------------------------
|   1 |            28 |                NULL |
|   2 |            29 |                NULL |
|   3 |            30 |                NULL |
---------------------------------------------
-------------------------------------------------------------------------
|  Id |                  De |                  Fr |                  En |
-------------------------------------------------------------------------
|  28 |          Image1.jpg |                NULL |               NULL  |
|  29 |          Image7.jpg |                NULL |               NULL  |
|  30 |    Picture_Test.png |                NULL |               NULL  |
-------------------------------------------------------------------------

感谢您的任何建议。

【问题讨论】:

  • 父表中有NULL时如何获取TranslationID?
  • Id 是一个标识列。 1. 在子表上插入 De = 父级名称 2. 更新父级的 TranslationId = 子级的(新)id
  • 在插入子表时使用SCOPE_IDENTITY(),获取子表的Id值。稍后,更新 Parent 表以​​填充 TranslationId。如果子表必须引用父表 TranslationId,请使用 Sequence 对象而不是 Identity,并获取唯一值以插入到两个表中。
  • 使用 OUTPUT 子句 docs.microsoft.com/en-us/sql/t-sql/queries/… 收集插入的 id 以更新原始表。
  • Serg 和 Sheerandra 你没事​​。我知道这个关键字。但在常规应用程序中,我会做一个循环(foreach,for,...)。我想知道如何在 SQL 中实现这一点? CTE,光标,...?

标签: sql sql-server tsql


【解决方案1】:

你可以这样做:

INSERT INTO Child
(
   Id
   ,De
   ,Fr
   ,En
)
OUTPUT Inserted.Id INTO #Temp
SELECT Id
       ,De
       ,Fr
       ,En
FROM @Values --If you are using a table type to insert into the Child table as a set based approach

;WITH CTE
AS
(
  SELECT ROW_NUMBER() OVER(ORDER BY Id) AS Rnk
  ,Id
  FROM #Temp

)
,CTE1 AS
(
  SELECT ROW_NUMBER() OVER(ORDER BY Id) AS Rnk
  ,*
  FROM Parent
)

UPDATE cte1
SET TranslationId = cte.Id
FROM CTE1 cte1
JOIN CTE cte ON cte.Rnk = cte1.Rnk

【讨论】:

  • 我尝试了您的方法,但我想它不适用于身份列(在父子节点上)。我用稍微不同的方式试了一下,结果数据搞砸了。
  • 我已经编辑了代码以将序列应用于父表并基于序列加入。试试代码并告诉我。
【解决方案2】:

Demo,假设Name在第一个表中是唯一的

create table tab1 (
  id int identity
 ,TranslationId int null
 ,Name nvarchar(max) null
 );
 insert tab1 (Name)
     values 
     ('Image1.jpg')
    ,('Image7.jpg')
    ,('Picture_Test.png')
    ,(null)

create table tab2 (
  id int identity (100,1)
 ,De nvarchar(max) null
 ,Fr nvarchar(max) null
 ,En nvarchar(max) null
 );

-- Update them 

declare @map table(
  name nvarchar(max) 
 ,ref int
  );

insert tab2 (de)
output inserted.De, inserted.id
into @map(Name, ref)
select Name
from tab1 src
where Name is not null and not exists (select 1 from tab2 t2 where t2.De = src.Name);

update t1 set TranslationId = ref, Name = null
from tab1 t1
join @map m on t1.Name = m.Name;

select * from tab1;
select * from tab2;

【讨论】:

    【解决方案3】:

    与此同时,我想出了如何去做。应用于数据库,查询如下所示:

    DECLARE @Temp TABLE (ImageId INT, Id INT)
    
    MERGE INTO Translation USING 
      (
      SELECT Image.Name AS Name, Image.Id AS ImageId
      FROM Candidate
      INNER JOIN Candidacy ON Candidate.Id = Candidacy.CandidateId
      INNER JOIN Election ON Candidacy.ElectionId = Election.Id
      INNER JOIN SmartVoteCandidate ON Candidate.Id = SmartVoteCandidate.CandidateId
      INNER JOIN Image ON SmartVoteCandidate.SpiderImageId = Image.Id
      WHERE Election.Id = 1575) AS temp ON 1 = 0
    WHEN NOT MATCHED THEN
      INSERT (De)
      VALUES (temp.Name)
      OUTPUT temp.ImageId, INSERTED.Id
      INTO @Temp (ImageId, Id);
    
    UPDATE Image
    SET Image.TranslationId = t.Id, Name = NULL
    FROM @Temp t
    WHERE Image.Id = t.ImageId
    

    该解决方案的灵感来自

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-06
      • 2018-06-25
      • 1970-01-01
      • 1970-01-01
      • 2018-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多