使用 table_1 和 table_2 数据更新 table_2 数据/T-SQL

Updating table_2 data using table_1 and table_2 data / T-SQL

场景

user@website.com 需要在 table 2 中具有与 admin@website.com.

相同的用户配置文件

目前 user@website.comuser_profile 50 而不是 user_profile 10 和 20。

描述

我想创建一个查询,在 Table_2 中输入与 user_email user@website.com 相同的 id_profiles,目前 admin@website.com.

我们唯一知道的是 user_email 用户和 table/column 名称。

Table 1

id_user user_email
1 admin@website.com
2 user@website.com

Table 2

id_user user_profile
1 10
1 20
2 50

Table 2(预期数据):

id_user user_profile
1 10
1 20
2 10
2 20

下面的查询没有按预期工作,因为它仅在 Table_2.

中没有包含 user_id '2' 的行时才插入数据
DECLARE @adminEmail nvarchar(255) = 'admin@website.com'
DECLARE @userEmail nvarchar(255) = 'user@website.com'
DECLARE @adminEmailID int = (SELECT id_user FROM Table_1 
                             WHERE user_profile = @adminEmail);

INSERT INTO Table_2 (id_user, user_profile)
    SELECT 
        (SELECT id_user FROM Table_1 
         WHERE user_email = @userEmail) AS id_user, 
        b.user_profile
    FROM 
        Table_2 b
    INNER JOIN 
        Table_1 a ON a.id_user = b.id_user
    WHERE 
        NOT EXISTS (SELECT * FROM Table_2
                    WHERE id_user = (SELECT id_user FROM Table_1 
                                     WHERE user_email = @userEmail))

您可以为此使用 MERGE

注意以下几点:

  • 必须pre-filter源和目标tables,使用CTE、视图或派生的tables,否则您将最终删除整个 table。 不要陷入将所有条件都放在ON.
  • 中的陷阱
  • 您需要找到目标用户的 ID,以便根据该 ID 插入。您不能在 MERGE 中执行此操作,因为 JOIN.
  • 将没有匹配的行
DECLARE @adminEmail nvarchar(255) = 'admin@website.com';
DECLARE @userEmail nvarchar(255) = 'user@website.com';
DECLARE @userEmailID int = (SELECT id_user FROM Table_1
                             WHERE user_email = @userEmail);
                             
WITH Source AS (
    SELECT t2.*
    FROM Table_2 t2
    JOIN Table_1 t1 ON t1.id_user = t2.id_user
    WHERE t1.user_email = @adminEmail
),
Target AS (
    SELECT t2.*
    FROM Table_2 t2
    WHERE t2.id_user = @userEmailID
)
MERGE Target t
USING Source s ON s.user_profile = t.user_profile
WHEN NOT MATCHED BY TARGET THEN
    INSERT (id_user, user_profile)
    VALUES (@userEmailID, s.user_profile)
WHEN NOT MATCHED BY SOURCE THEN
    DELETE
;

db<>fiddle

  • 根据联接的复杂性,将此作为单独的 INSERTDELETE 语句执行可能更容易且性能更高
DECLARE @adminEmail nvarchar(255) = 'admin@website.com';
DECLARE @userEmail nvarchar(255) = 'user@website.com';

INSERT Table_2 (id_user, user_profile)
SELECT t1User.id_user, t2.user_profile
FROM Table_2 t2
JOIN Table_1 t1Admin ON t1Admin.id_user = t2.id_user
    AND t1Admin.user_email = @adminEmail
JOIN Table_1 t1User ON t1User.user_email = @userEmail
WHERE NOT EXISTS (SELECT 1
    FROM Table_2 t2Existing
    WHERE t2Existing.id_user = t1User.id_user
      AND t2Existing.user_profile = t2.user_profile);
      
DELETE t2
FROM Table_2 t2
JOIN Table_1 t1User ON t1User.id_user = t2.id_user
    AND t1User.user_email = @userEmail
WHERE NOT EXISTS (SELECT 1
    FROM Table_2 t2Admin
    JOIN Table_1 t1Admin ON t1Admin.id_user = t2Admin.id_user
    WHERE t1Admin.user_email = @adminEmail
      AND t2Admin.user_profile = t2.user_profile);

db<>fiddle