从外部或变量将 table 名称传递给 INSERT INTO tablename?
Pass a table name to INSERT INTO tablename from outside or a variable?
我有更多 tables,其中包含大量生产中的条目,我想将其移至历史数据库。
我已尝试使用此查询,但效果很好,但我不知道是否有可能从外部提供 tables 的名称。我不想为每个数据库和 table.
编写此查询
INSERT INTO [database.history].dbo.tablename
SELECT *
FROM [database.live].dbo.table
DELETE FROM [database.history].dbo.tablename
我想从外部提供数据库和 table 的名称。我使用小巧的 ORM。有什么解决方案可以使用类似于其他类型的东西吗?例如。
DECLARE @ProductionTableName nvarchar(250) = '[database.live].dbo.table'
我的数据库在同一台服务器上。
我的查询在文件中,我的电话看起来像。
string query = queryFile;
var param = new {Parameter1= stringValue};
var result = Connection.Query<long>(query, param);
如果您使用的是 Dapper,则意味着您使用的是 C# 代码中的查询,而不是存储过程中的查询。您可以在 app.config 中添加 ProdDb 和 HistoryDb 并从那里使用它。
编辑:您还可以为两个数据库构建不同的连接字符串,并打开您想要在代码中使用的任何连接。
如果您的数据库在同一台服务器上,您可以使用 SQL Server Replication 功能将生产数据库复制到历史数据库。
您不能在 SQL 中参数化标识符。你可以做的是使用动态 SQL.
但是请注意,除非正确使用,否则使用动态 SQL 可能很危险。
基本规则实际上非常简单 - 您必须参数化您可以参数化的参数,并将您不能参数化的白名单。
更多详情,请阅读我的博客 post The do’s and don’ts of dynamic SQL for SQL Server.
此外,由于您要将记录从一个 table 移动到另一个,您应该使用事务,否则,如果您的删除语句因错误而失败,插入语句将不会回滚,并且您将以存在于两个数据库中的行结束。
有关更多信息,请阅读 Understanding Cross-Database Transactions in SQL Server 红门。
请注意,如果历史数据库与实时数据库位于不同的服务器上,您将需要 distributed transaction。
一个有效的例子是这样的:
DECLARE @TableName sysname = 'TableName',
@LineBreak nchar(2) = NCHAR(13) + NCHAR(10),
@Sql nvarchar(4000);
IF EXISTS(
SELECT 1
FROM [database.live].Information_schema.Tables
WHERE Table_Name = @TableName
)
BEGIN
SET @SQL = 'BEGIN TRANSACTION' + @LineBreak +
'BEGIN TRY' + @LineBreak +
'INSERT INTO [database.history].dbo.' + @TableName + @LineBreak +
'SELECT *' + @LineBreak +
'FROM [database.live].dbo.' + @TableName + @LineBreak +
'DELETE FROM [database.history].dbo.' + @TableName +
'COMMIT TRANSACTION' + @LineBreak +
'END TRY' + @LineBreak +
'BEGIN CATCH' + @LineBreak +
'IF @@TRANCOUNT > 0' + @LineBreak +
' ROLLBACK TRANSACTION' + @LineBreak +
'END CATCH' + @LineBreak
-- When working with dynamic SQL, Print is your best friend.
PRINT @SQL
-- Once you've verified that the SQL looks ok, you can unremark the EXEC statemet.
--EXEC sp_ExecuteSql @SQL
END
但是请注意,使用 insert
语句而不指定列列表以及使用 select *
.
被认为是不好的做法
要将其添加到您的查询中,您可以查询 sys.columns
以获取所需的 table 的列。
我还注意到问题中的代码不包含 where
子句 - 这意味着该行的全部内容将从实时数据库移动到历史数据库。
我有更多 tables,其中包含大量生产中的条目,我想将其移至历史数据库。
我已尝试使用此查询,但效果很好,但我不知道是否有可能从外部提供 tables 的名称。我不想为每个数据库和 table.
编写此查询INSERT INTO [database.history].dbo.tablename
SELECT *
FROM [database.live].dbo.table
DELETE FROM [database.history].dbo.tablename
我想从外部提供数据库和 table 的名称。我使用小巧的 ORM。有什么解决方案可以使用类似于其他类型的东西吗?例如。
DECLARE @ProductionTableName nvarchar(250) = '[database.live].dbo.table'
我的数据库在同一台服务器上。
我的查询在文件中,我的电话看起来像。
string query = queryFile;
var param = new {Parameter1= stringValue};
var result = Connection.Query<long>(query, param);
如果您使用的是 Dapper,则意味着您使用的是 C# 代码中的查询,而不是存储过程中的查询。您可以在 app.config 中添加 ProdDb 和 HistoryDb 并从那里使用它。
编辑:您还可以为两个数据库构建不同的连接字符串,并打开您想要在代码中使用的任何连接。
如果您的数据库在同一台服务器上,您可以使用 SQL Server Replication 功能将生产数据库复制到历史数据库。
您不能在 SQL 中参数化标识符。你可以做的是使用动态 SQL.
但是请注意,除非正确使用,否则使用动态 SQL 可能很危险。
基本规则实际上非常简单 - 您必须参数化您可以参数化的参数,并将您不能参数化的白名单。
更多详情,请阅读我的博客 post The do’s and don’ts of dynamic SQL for SQL Server.
此外,由于您要将记录从一个 table 移动到另一个,您应该使用事务,否则,如果您的删除语句因错误而失败,插入语句将不会回滚,并且您将以存在于两个数据库中的行结束。
有关更多信息,请阅读 Understanding Cross-Database Transactions in SQL Server 红门。
请注意,如果历史数据库与实时数据库位于不同的服务器上,您将需要 distributed transaction。
一个有效的例子是这样的:
DECLARE @TableName sysname = 'TableName',
@LineBreak nchar(2) = NCHAR(13) + NCHAR(10),
@Sql nvarchar(4000);
IF EXISTS(
SELECT 1
FROM [database.live].Information_schema.Tables
WHERE Table_Name = @TableName
)
BEGIN
SET @SQL = 'BEGIN TRANSACTION' + @LineBreak +
'BEGIN TRY' + @LineBreak +
'INSERT INTO [database.history].dbo.' + @TableName + @LineBreak +
'SELECT *' + @LineBreak +
'FROM [database.live].dbo.' + @TableName + @LineBreak +
'DELETE FROM [database.history].dbo.' + @TableName +
'COMMIT TRANSACTION' + @LineBreak +
'END TRY' + @LineBreak +
'BEGIN CATCH' + @LineBreak +
'IF @@TRANCOUNT > 0' + @LineBreak +
' ROLLBACK TRANSACTION' + @LineBreak +
'END CATCH' + @LineBreak
-- When working with dynamic SQL, Print is your best friend.
PRINT @SQL
-- Once you've verified that the SQL looks ok, you can unremark the EXEC statemet.
--EXEC sp_ExecuteSql @SQL
END
但是请注意,使用 insert
语句而不指定列列表以及使用 select *
.
被认为是不好的做法
要将其添加到您的查询中,您可以查询 sys.columns
以获取所需的 table 的列。
我还注意到问题中的代码不包含 where
子句 - 这意味着该行的全部内容将从实时数据库移动到历史数据库。