【问题标题】:Is there a way to do another query within the insert query?有没有办法在插入查询中进行另一个查询?
【发布时间】:2011-09-13 20:41:30
【问题描述】:

好的,这就是我的查询...我刚刚添加了 ACCOUNTID 和 @accountID 部分,这显然不起作用

INSERT INTO Leads (
    LEADID,
    CREATEUSER,
    CREATEDATE,
    FIRSTNAME,
    MODIFYDATE,
        ACCOUNTID
) 
SELECT 
       'Q' + cast(floor(999997 * RAND(convert(varbinary, newid()))) as varchar(20)) 
       ,'U6UJ9000S'
       ,CURRENT_TIMESTAMP
       ,'U6UJ9000S'    
       ,name
       ,@accountID

  FROM Temp

我要做的是先插入到帐户表中,然后获取该 ID 并将插入 ID 添加到此插入到潜在客户表中。这有可能吗

所以基本上对于 Temp 表中的每条记录,我需要在 account 表中插入一条没有值的记录,只需要 account_id,所以当我在潜在客户表中插入时,我有帐户 id 来进行插入

【问题讨论】:

标签: sql sql-server sql-server-2008 insert


【解决方案1】:

设置:

USE TempDB;
GO

CREATE TABLE dbo.Leads
(
    LeadID VARCHAR(64),
    CreateUser VARCHAR(32),
    CreateDate DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    FirstName VARCHAR(32),
    AccountID INT
);

CREATE TABLE dbo.Accounts
(
    AccountID INT IDENTITY(1,1),
    name VARCHAR(32) /* , ... other columns ... */
);

CREATE TABLE dbo.Temp(name VARCHAR(32));

INSERT dbo.Temp SELECT 'foo'
UNION SELECT 'bar';

查询:

INSERT dbo.Accounts
(
    name
)
OUTPUT
    'Q' + cast(floor(999997 * RAND(convert(varbinary, newid()))) as varchar(20)),
    'U6UJ9000S',
    CURRENT_TIMESTAMP,
    inserted.name,
    inserted.AccountID
INTO dbo.Leads
SELECT name
FROM dbo.Temp;

检查:

SELECT * FROM dbo.Accounts;
SELECT * FROM dbo.Leads;

清理:

USE tempdb;
GO
DROP TABLE dbo.Temp, dbo.Accounts, dbo.Leads;

【讨论】:

  • 这种方式也可以,我没有意识到 INSERTS 可以像这样菊花链。
  • @Wil 这不是微不足道的,特别是如果您需要源表中的数据最终出现在第二个表中,但 不是 第一个......但在这种情况下(假设name 和 firstname 应该是相同的)它的工作原理......
  • @Aaron 你能向我解释一下吗...对不起,我是 PHP 和 mysql 开发人员,我对这里的工作并没有完全了解
  • 我不知道如何解释它,除了有一个 OUTPUT 子句使插入的数据可用于在同一语句中进行未来操作。所以它基本上是在一个语句中插入两个表,使用伪表“插入” - 它临时保存插入的数据。我提供了一个链接作为对您问题的评论,以便您查看官方文档。
  • 实际上,在大多数情况下,您可能确实想要这样做,因此定义了一个 FK 约束,您会遇到错误The target table 'dbo.Leads' of the OUTPUT INTO clause cannot be on either side of a (primary key, foreign key) relationship. Found reference constraint 'FK__Name'My answer 提供了解决方法。
【解决方案2】:

在 Aaron 使用可组合 DML 的实践中,您可能最终会遇到的问题是,实际上您可能会定义一个 FK 以将 Leads(AccountId) 约束为有效值,在这种情况下您会遇到错误。

OUTPUT INTO 子句的目标表 'dbo.Leads' 不能在 (主键,外键)关系的任一侧。成立 引用约束“FK_foo”。

为了避免这个问题,你可以使用

INSERT INTO dbo.Leads
EXEC('
INSERT INTO dbo.Accounts
OUTPUT
    ''Q'' + cast(floor(999997 * RAND(convert(varbinary, newid()))) as varchar(20)),
    ''U6UJ9000S'',
    CURRENT_TIMESTAMP,
    inserted.name,
    inserted.AccountID
SELECT name
FROM dbo.Temp;
')

【讨论】:

    【解决方案3】:

    它不起作用,因为您插入了 6 个值,但您只指定了 5 列:

    这些是 5 列:

    LEADID,
        CREATEUSER,
        CREATEDATE,
        FIRSTNAME,
            ACCOUNTID
    

    这些是 6 个值:

    'Q' + cast(floor(999997 * RAND(convert(varbinary, newid()))) as varchar(20)) 
           ,'U6UJ9000S'
           ,CURRENT_TIMESTAMP
           ,'U6UJ9000S'    
           ,name
           ,@accountID
    

    我不知道你从哪里得到@accountID,但我想你在上面的其他地方定义了它。

    你可以得到@accountID,在你插入到Account表之后:

    select @accountID=scope_identity()
    

    然后执行插入到 Leads 表中。

    更新:示例:

    declare @accountID int 
    INSERT INTO Account (col1,col2,col...)
    values ('foo','bar','baz')
    
    select @accountID=SCOPE_IDENTITY()
    
    INSERT INTO Leads (
        LEADID,
        CREATEUSER,
        CREATEDATE,
        FIRSTNAME,
            ACCOUNTID
    ) 
    values 
    (
          'Q' + cast(floor(999997 * RAND(convert(varbinary, newid()))) as varchar(20))  --leadid
           ,'U6UJ9000S' --createuser
           ,CURRENT_TIMESTAMP  --createdate
           ,t.name --firstname
           ,@accountID --accountID
    )
    

    【讨论】:

    • 不,我有 6 和 6,这是一个错字...... accountid 是我的问题的全部内容......在我的问题的顶部,你会看到我说它显然不起作用
    • 你能解释一下这个 select @accountID=scope_identity() 在我的脚本中的位置吗
    • 选择 @accountID=scope_identity() 应该是您执行 INSERT INTO Account 后的第一行(您在问题中提到您在 Account 表中进行了插入,不是吗?) SCOPE_IDENTITY() 函数返回在当前范围内插入 Account 表的最后一条记录的最后一个 id。在这里阅读更多:msdn.microsoft.com/en-us/library/ms190315.aspx
    • 我需要做的是在我在潜在客户表中插入之前插入到帐户表中......@accountID 是我试图解释......我没有任何代码生成那个呢
    • @Alex 我将使用您的代码通过一个完整的示例更新我的答案...敬请期待:)
    【解决方案4】:

    将变量设置为 Scope_identity()(返回最后创建的 id)并使用它

    【讨论】:

    • 我该怎么做...我是一个 mysql php 开发人员,而 SQL Server 不是我的专长
    • 好吧,没有冒犯,但如果 SQL Server“有点超出你的专业”,那么你为什么要做 SQL Server 工作?如果您需要使用 SQL Server,那么您应该致力于学习 SQL Server 的工作原理,或者聘请已经知道的人。
    【解决方案5】:

    对于 SQL Server 2005 或更高版本,您可以使用 OUTPUT 子句。

    CREATE TABLE #Inserted (AccountID, AccountName)
    
    INSERT Account (AccountName)
    OUTPUT Inserted.AccountID, Inserted.AccountName
    INTO #Inserted
    
    SELECT AccountName
    FROM Temp
    
    INSERT Leads (
        LEADID,
        CREATEUSER,
        CREATEDATE,
        FIRSTNAME,
            ACCOUNTID
    ) 
    SELECT 
           'Q' + cast(floor(999997 * RAND(convert(varbinary, newid()))) as varchar(20)) 
           ,'U6UJ9000S'
           ,CURRENT_TIMESTAMP
           ,t.name
           ,i.AccountID
    
      FROM Temp AS t
      JOIN #Inserted AS i ON t.AccountName= i.AccountName
    

    【讨论】:

    • 你能解释一下#Inserted 部分以及这是什么
    • 这是一个临时表。这些是非常基本的 SQL Server 概念(临时表、变量)。该脚本所做的是创建一个临时表来保存插入的 AccountID。 INSERT 之后的 OUTPUT 子句会将 accountid 和 name 输出到#Inserted。从那里您可以将新插入的 accountids 链接回 Temp 中的 accountname(我假设它存在)以插入到 Leads 表中。
    【解决方案6】:

    您可以声明一个变量,将其设置为所需的 id 并在插入中使用该变量。

    【讨论】:

    • Alex,在 SQL Server Management Studio 中按 F1。单击“搜索”选项卡。
    猜你喜欢
    • 1970-01-01
    • 2021-08-19
    • 1970-01-01
    • 1970-01-01
    • 2019-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多