从存储过程复制表的数据

发布于 2024-08-30 04:01:22 字数 990 浏览 5 评论 0原文

我正在学习如何使用 SQL 和存储过程。我知道语法不正确:

使用存储过程将数据从一个表复制到另一个数据库上的另一个表中。问题是我不知道要复制到哪个表或哪个数据库。我希望它使用参数而不是专门指定列。

我有 2 个数据库(Master_db 和 Master_copy),每个数据库上都有相同的表结构。

我想快速选择 Master_db 中的一个表并将该表的数据复制到同名的 Master_copy 表中。我想出了这样的事情:

USE Master_DB
CREATE PROCEDURE TransferData
DEFINE @tableFrom, @tableTo, @databaseTo;

INSERT INTO @databaseTo.dbo.@databaseTo
SELECT * FROM Master_DB.dbo.@tableFrom
GO;

我能得到的最接近的就是这个。现在的问题是我有一个时间戳列,并且出现错误:

“无法将显式值插入时间戳列。使用带有列列表的 INSERT 来排除时间戳列,或将 DEFAULT 插入时间戳列。”

USE Kenneth_Integration
GO
CREATE PROCEDURE TransferData
  @table  SYSNAME
  ,@databaseTo SYSNAME
AS
DECLARE @sql NVARCHAR(MAX)

SET @sql = 'DELETE FROM ' + @databaseTo + '..' + @table + ' set identity_insert ' + @databaseTo + '.dbo.' + @table + 
    ' on INSERT INTO ' + @databaseTo + '.dbo.' + @table + ' SELECT * FROM Kenneth_Integration.dbo.' + @table

EXEC sp_executesql @sql
GO

如何使用此 SP 解决此错误?

I am learning how to use SQL and Stored Procedures. I know the syntax is incorrect:

Copy data from one table into another table on another Database with a Stored Procedure. The problem is I don't know what table or what database to copy to. I want it to use parameters and not specify the columns specifically.

I have 2 Databases (Master_db and Master_copy) and the same table structure on each DB.

I want to quickly select a table in Master_db and copy that table's data into Master_copy table with same name. I have come up with something like this:

USE Master_DB
CREATE PROCEDURE TransferData
DEFINE @tableFrom, @tableTo, @databaseTo;

INSERT INTO @databaseTo.dbo.@databaseTo
SELECT * FROM Master_DB.dbo.@tableFrom
GO;

The closest I could get was this. The problem now is that I have a Timestamp column and that rendered an error:

"Cannot insert an explicit value into a timestamp column. Use INSERT with a column list to exclude the timestamp column, or insert a DEFAULT into the timestamp column."

USE Kenneth_Integration
GO
CREATE PROCEDURE TransferData
  @table  SYSNAME
  ,@databaseTo SYSNAME
AS
DECLARE @sql NVARCHAR(MAX)

SET @sql = 'DELETE FROM ' + @databaseTo + '..' + @table + ' set identity_insert ' + @databaseTo + '.dbo.' + @table + 
    ' on INSERT INTO ' + @databaseTo + '.dbo.' + @table + ' SELECT * FROM Kenneth_Integration.dbo.' + @table

EXEC sp_executesql @sql
GO

How can I go around this error with this SP?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

極樂鬼 2024-09-06 04:01:22

SQL 查询中的对象名称无法按照您尝试的方式进行参数化。

要使其正常工作,您需要使用动态 SQL:

USE Master_DB
CREATE PROCEDURE TransferData
 @tableFrom   SYSNAME
 ,@tableTo    SYSNAME
 ,@databaseTo SYSNAME
AS
DECLARE @sql NVARCHAR(MAX)
SET @sql = 'INSERT INTO ' + @databaseTo+ '.dbo.' + @tableTo + '
            SELECT * FROM Master_DB.dbo.' + @tableFrom

EXEC sp_executesql @sql
GO;

Object names in SQL queries cannot be parameterised in the way you are attempting.

To get this to work, you need to use dynamic SQL:

USE Master_DB
CREATE PROCEDURE TransferData
 @tableFrom   SYSNAME
 ,@tableTo    SYSNAME
 ,@databaseTo SYSNAME
AS
DECLARE @sql NVARCHAR(MAX)
SET @sql = 'INSERT INTO ' + @databaseTo+ '.dbo.' + @tableTo + '
            SELECT * FROM Master_DB.dbo.' + @tableFrom

EXEC sp_executesql @sql
GO;
小女人ら 2024-09-06 04:01:22

只有动态 SQL 允许变量作为表名。例如0le:

create procedure dbo.TransferData(
    @src varchar(50),
    @dest varchar(50))
as
declare @query varchar(500)
set @query = 'INSERT INTO ' + @src +
    'SELECT * FROM ' + @dest
exec @query
go

Only dynamic SQL allows variables as table names. For examp0le:

create procedure dbo.TransferData(
    @src varchar(50),
    @dest varchar(50))
as
declare @query varchar(500)
set @query = 'INSERT INTO ' + @src +
    'SELECT * FROM ' + @dest
exec @query
go
好菇凉咱不稀罕他 2024-09-06 04:01:22

我同意@EdHarper 的观点,构建一个字符串然后运行 ​​sp_executesql 可能是你最好的答案。

需要记住的两件事是我在前面的答案中看不到的:

1)您之前可能已经将数据复制到 Master_copy 数据库表中,因此您可能需要在开始复制之前删除目标表中的数据手术。

2) 如果 Master_copy 表中有任何标识列(例如,因为您使用相同的 Sql 脚本生成 Master_db 和 Master_copy 表),那么您需要确保可以覆盖标识值(这可以通过 命令上设置identity_insert)。

因此,作为替代方案(没有必要重复回答)并且当您知道数据库名称时,您可以简单地对该方法进行非规范化并为每个表编写一个简单的存储过程。

假设您有一个名为“person”的表,您可以

create procedure TransferDataPerson 
as

delete from Master_copy..Person

set identity_insert Master_copy..Person on

insert into Master_copy..Person
select * from Master_db..Person

为每个表编写:...等等。

I would agree with @EdHarper that building a string and then running sp_executesql is probably your best answer.

Two things to bear in mind that I can't see in the previous answers:

1) You may have already copied the data into the Master_copy database tables previously, so you probably need to delete the data in the target table before you start your copy operation.

2) If you have any identity columns in the Master_copy tables (because you used the same Sql script to generate the Master_db and Master_copy tables for example) then you need to ensure that you can overwrite identity values (this can be done by the set identity_insert on command).

So as an alternative (there is no point to another repeated answer) and as you know the database names you could simply denormalize this approach and write a simple stored procedure for each table.

Say you have a table called 'person' you could write:

create procedure TransferDataPerson 
as

delete from Master_copy..Person

set identity_insert Master_copy..Person on

insert into Master_copy..Person
select * from Master_db..Person

... and so on for each table.

凉世弥音 2024-09-06 04:01:22

我的建议是编写返回表的函数
比使用 insert select 语句

过程和函数之间的区别比你不能写
选择过程但是
你可以写
选择功能

My suggestion is to write function which return table
than use insert select statement

Difference between procedure and function than you cannot write
select procedure but
you can write
select function

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文