Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.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 Server:是否可以同时插入到两个表中?_Sql_Sql Server_Insert_Temp Tables - Fatal编程技术网

SQL Server:是否可以同时插入到两个表中?

SQL Server:是否可以同时插入到两个表中?,sql,sql-server,insert,temp-tables,Sql,Sql Server,Insert,Temp Tables,我的数据库包含三个表,分别称为Object\u Table、Data\u Table和Link\u Table。链接表只包含两列,即对象记录的标识和数据记录的标识 我想从链接到一个给定对象标识的data\u表复制数据,并为不同的给定对象标识将相应的记录插入data\u表和Link\u表 I可以通过选择一个表变量并通过为每个迭代执行两次插入循环来实现这一点 这是最好的方法吗 编辑:我想避免循环有两个原因,第一个原因是我很懒,循环/临时表需要更多的代码,更多的代码意味着更多的地方会出错,第二个原因是

我的数据库包含三个表,分别称为
Object\u Table
Data\u Table
Link\u Table
。链接表只包含两列,即对象记录的标识和数据记录的标识

我想从链接到一个给定对象标识的
data\u表
复制数据,并为不同的给定对象标识将相应的记录插入
data\u表
Link\u表

I可以通过选择一个表变量并通过为每个迭代执行两次插入循环来实现这一点

这是最好的方法吗

编辑:我想避免循环有两个原因,第一个原因是我很懒,循环/临时表需要更多的代码,更多的代码意味着更多的地方会出错,第二个原因是担心性能


我可以在一次插入中复制所有数据,但是如何让链接表链接到新的数据记录,其中每个记录都有一个新的id?

如果您希望操作或多或少是原子的,我会确保将它们包装到事务中。这样你就可以确定两者都发生了,或者两者都没有发生

Insert一次只能对一个表进行操作。多个插入必须有多个语句

我不知道你需要在一个表变量中循环-你不能在一个表中使用mass插入,然后在另一个表中使用mass插入吗


顺便说一下,我猜你的意思是从Object_表复制数据;否则这个问题就没有意义了。

您仍然需要两个
INSERT
语句,但听起来您想从第一个INSERT中获取
标识,然后在第二个INSERT中使用它,在这种情况下,您可能需要在一个语句中查看
输出
输出到

:否

在一笔交易中:是


好消息是,上面的代码也保证是原子的,并且可以在单个函数调用中使用一个sql字符串从客户端应用程序发送到服务器,就像它是一条语句一样。您还可以对一个表应用触发器,以获得单个插入的效果。但是,最终还是两条语句,您可能不想为每个插入运行触发器。

听起来链接表捕获了对象表和数据表之间的多对多关系

我的建议是使用存储过程来管理事务。如果要插入到对象或数据表中,请执行插入操作,获取新ID并将其插入到链接表中


这使您的所有逻辑都可以封装在一个易于调用的存储过程中。

您可以创建一个视图,选择insert语句所需的列名,添加一个insert而不是insert触发器,然后插入到该视图中。

在Oracle中执行多任务插入之前,您可以使用一种技巧,将插入到定义了INSTEAD OF触发器的视图中,以执行插入。这可以在SQL Server中完成吗?

下面使用表变量设置了我遇到的情况

DECLARE @Object_Table TABLE
(
    Id INT NOT NULL PRIMARY KEY
)

DECLARE @Link_Table TABLE
(
    ObjectId INT NOT NULL,
    DataId INT NOT NULL
)

DECLARE @Data_Table TABLE
(
    Id INT NOT NULL Identity(1,1),
    Data VARCHAR(50) NOT NULL
)

-- create two objects '1' and '2'
INSERT INTO @Object_Table (Id) VALUES (1)
INSERT INTO @Object_Table (Id) VALUES (2)

-- create some data
INSERT INTO @Data_Table (Data) VALUES ('Data One')
INSERT INTO @Data_Table (Data) VALUES ('Data Two')

-- link all data to first object
INSERT INTO @Link_Table (ObjectId, DataId)
SELECT Objects.Id, Data.Id
FROM @Object_Table AS Objects, @Data_Table AS Data
WHERE Objects.Id = 1
多亏了另一个为我指明输出条款的人,我可以演示一个解决方案:

-- now I want to copy the data from from object 1 to object 2 without looping
INSERT INTO @Data_Table (Data)
OUTPUT 2, INSERTED.Id INTO @Link_Table (ObjectId, DataId)
SELECT Data.Data
FROM @Data_Table AS Data INNER JOIN @Link_Table AS Link ON Data.Id = Link.DataId
                INNER JOIN @Object_Table AS Objects ON Link.ObjectId = Objects.Id 
WHERE Objects.Id = 1
然而,事实证明,由于以下错误,在现实生活中并不是那么简单

输出到子句不能打开 a(主键,外键)的任一侧 (关键)关系


我仍然可以
输出到一个临时表中,然后完成正常插入。因此,我可以避免循环,但无法避免临时表。

//如果要插入与第一个表相同的表

$qry = "INSERT INTO table (one, two, three) VALUES('$one','$two','$three')";

$result = @mysql_query($qry);

$qry2 = "INSERT INTO table2 (one,two, three) VVALUES('$one','$two','$three')";

$result = @mysql_query($qry2);

//或者,如果要插入表1的某些部分

 $qry = "INSERT INTO table (one, two, three) VALUES('$one','$two','$three')";


  $result = @mysql_query($qry);

 $qry2 = "INSERT INTO table2 (two) VALUES('$two')";

 $result = @mysql_query($qry2);
//我知道它看起来太好了,不可能是正确的,但它可以工作,您可以继续添加查询,只需更改

    "$qry"-number and number in @mysql_query($qry"")


我有17个表,这些表已经使用过了。

我想强调使用

-- ================================================
-- Template generated from Template Explorer using:
-- Create Procedure (New Menu).SQL
--
-- Use the Specify Values for Template Parameters 
-- command (Ctrl-Shift-M) to fill in the parameter 
-- values below.
--
-- This block of comments will not be included in
-- the definition of the procedure.
-- ================================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE InsetIntoTwoTable

(
@name nvarchar(50),
@Email nvarchar(50)
)

AS
BEGIN

    SET NOCOUNT ON;


    insert into dbo.info(name) values (@name)
    insert into dbo.login(Email) values (@Email)
END
GO
SET XACT_ABORT ON;
用于具有多个sql语句的MSSQL事务

见: 他们提供了一个很好的例子

因此,最终代码应该如下所示:

SET XACT_ABORT ON;

BEGIN TRANSACTION
   DECLARE @DataID int;
   INSERT INTO DataTable (Column1 ...) VALUES (....);
   SELECT @DataID = scope_identity();
   INSERT INTO LinkTable VALUES (@ObjectID, @DataID);
COMMIT

我没有兴趣尝试用一个插件来做,当用两个插件来做的时候效果非常好。您的意思是要确保两次插入都已完成?然后您必须检查此提交/回滚指令。我很乐意使用两个插入,只是需要插入到链接表中的标识是第一次插入时生成的标识。谢谢!我不知道OUTPUT关键字,这正是我想要的+1是否可以一次使用“输出到”两次sql@V.Wu我不这么认为,我将不得不设置一个测试来查看。这是我一直在寻找的。谢谢:)@Joel,问得好。大概有人希望有另一种现实,而你是坏消息的传递者最好的答案!我浪费了很多时间试图弄清楚如何在单个查询中链接插入。非常感谢。这并不能解决问题。他想插入从对象表读取的数据。即,
插入到。。。选择…
语句。上述代码如何读取或循环对象表数据。然后,您仍然需要使用询问者不想使用的表变量。确保这解决了问题。也许我没有为此编写所有的代码,但是OP也没有共享他想要复制的所有列。此答案中演示的功能将允许OP执行其要求的操作。。。运行查询以创建记录,获取新记录的ID,并以原子方式将该ID用于第二条记录。OP已经知道如何进行插入/选择。这是他丢失的部分。如果动作被包装在事务中,那么它们是原子的,而不是“或多或少”原子的。除非您指定隔离级别,否则不一定保证隔离级别。我认为这不是一个有效的答案,因为它使用的是添加signif的数据库表
SET XACT_ABORT ON;

BEGIN TRANSACTION
   DECLARE @DataID int;
   INSERT INTO DataTable (Column1 ...) VALUES (....);
   SELECT @DataID = scope_identity();
   INSERT INTO LinkTable VALUES (@ObjectID, @DataID);
COMMIT