我有一项任务,我想将所有数据从一个数据库复制到另一个数据库&跳过2张桌子。有超过200个表。
我已准备好第二个数据库的表结构。
作为解决方案,我创建了一个页面&点击按钮,我有以下代码: -
DataSet ds = new DataSet();
string connectionString = "Data Source=COMP112\\MSSQLSERVER2014;Initial Catalog=HCMBL;Integrated Security=True;Persist Security Info=True";
SqlConnection con = new SqlConnection(connectionString);
//render table name from database
string sqlTable = "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' and TABLE_Schema='" + Session["SchemaName"].ToString() + "' and TABLE_NAME!='ENTRY' and TABLE_NAME!='OT' and TABLE_NAME!='BL_ENTRY' and TABLE_NAME!='BL_OT'";
con.Open();
SqlDataAdapter da = new SqlDataAdapter();
SqlCommand cmd = new SqlCommand(sqlTable, con);
cmd.CommandType = CommandType.Text;
da.SelectCommand = cmd;
da.Fill(ds);
con.Close();
//render connection string from WebConfig file
string strcon = ConfigurationManager.ConnectionStrings["SPSchema"].ConnectionString;
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
if (!(ds.Tables[0].Rows[i]["TABLE_NAME"].ToString().Contains("Asp")))
{
string deleteQuery = "Truncate table " + Session["SchemaName"].ToString() + "." + ds.Tables[0].Rows[i]["TABLE_NAME"];
con.Open();
SqlCommand cmdDelete = new SqlCommand(deleteQuery, con);
cmdDelete.ExecuteNonQuery();
con.Close();
DataSet dataSet = new DataSet();
SqlConnection conn = new SqlConnection(strcon);
conn.Open();
string selectData = "select * from " + Session["SchemaName"].ToString() + "." + ds.Tables[0].Rows[i]["TABLE_NAME"];
SqlCommand command = new SqlCommand(selectData, conn);
DataTable dataTable = new DataTable();
SqlDataAdapter dataAdapter = new SqlDataAdapter(selectData, conn);
dataAdapter.FillSchema(dataSet, SchemaType.Mapped);
dataAdapter.Fill(dataSet);
dataTable = dataSet.Tables[0];
conn.Close();
if (dataSet.Tables[0].Rows.Count > 0)
{
//Connect to second Database and Insert row/rows.
SqlConnection conn2 = new SqlConnection(connectionString);
conn2.Open();
SqlBulkCopy bulkCopy = new SqlBulkCopy(conn2);
bulkCopy.DestinationTableName = Session["SchemaName"].ToString() + "." + ds.Tables[0].Rows[i]["TABLE_NAME"].ToString();
bulkCopy.WriteToServer(dataTable);
conn2.Close();
}
}
}
当我在少于10个表中插入数据后运行上面的代码时,它会给出内存异常&amp;程序崩溃。
如何处理?我尝试增加SQL Server的内存容量,但仍然是同样的错误。
还有其他方法可以完成任务吗?
答案 0 :(得分:5)
您所做的与最佳解决方案相去甚远。您正在使用ASP.NET MVC流程将整个数据库的所有数据存入内存,然后将其输出到另一个数据库。如果您的数据库不仅仅是小而重要的,那么这绝对会填满您流程的内存。
这种类型的任务绝不应该通过进程的内存来完成,而是使用某种形式的备份/还原模式。
您应该查看SSIS projects并创建提取,传输和加载(ETL)解决方案,该解决方案可以异步从ASP.NET MVC解决方案中触发。
可以通过以下方式从C#代码触发SSIS解决方案:
var app = new Application();
var package = app.LoadPackage("compiled-package.dtsx", null);
var results = package.Execute();
请参阅此问题以获取更多信息(不是专门关于复制数据库,但有关于从代码触发SSIS包的信息):How to execute an SSIS package from .NET?
<强>替代地强>
您还可以选择同时对两个数据库运行查询,但这需要一些额外的管道才能完成。 ASP.NET MVC解决方案的用户帐户需要能够访问这两个数据库。如果您的数据库托管在不同的服务器上,您还需要链接一台服务器到另一台服务器:Create linked servers
要直接从insert
的输出执行select
,请考虑以下事项:
string source = "NAME_OF_SOURCE_DATABASE";
string target = "NAME_OF_TARGET_DATABASE";
string schema = Session["SchemaName"].ToString();
string table = ds.Tables[0].Rows[i]["TABLE_NAME"];
// Uncomment this if you need to deal with autoincrement columns
/*string idInsQuery = $"SET IDENTITY_INSERT {target}.{schema}.{table} ON";
var idInsCommand = new SqlCommand(idInsQuery, conn);
idInsCommand.ExecuteNonQuery();*/
string insQuery = $"INSERT INTO {target}.{schema}.{table} SELECT * FROM {source}.{schema}.{table}";
var insCommand = new SqlCommand(insQuery, conn);
insCommand.ExecuteNonQuery();
// Uncomment this if you need to deal with autoincrement columns
/*string idInsQuery2 = $"SET IDENTITY_INSERT {target}.{schema}.{table} OFF";
var idInsCommand2 = new SqlCommand(idInsQuery2, conn);
idInsCommand2.ExecuteNonQuery();*/
如果表结构相同,这将仅。 autoincrement
ID或具有默认值的列可能存在问题。
答案 1 :(得分:1)
这会将数据从数据库1中的表复制到数据库2中的表
Insert into db2.dbo.table2 (col1,col2)
Select col1,col2 from db1.dbo.table1
运行此sql语句,数据将被复制而无需往返您的应用程序。
答案 2 :(得分:0)
如果您发现我的方法很有用,请告诉我。 首先,为什么你要写下一个完整的应用程序来完成这项工作,而 SQL Server继承了属性。
我的方法是配置链接服务器并配置要复制哪些表而不是哪些表。 https://docs.microsoft.com/en-us/sql/relational-databases/linked-servers/create-linked-servers-sql-server-database-engine
其次,你可以写下简单的存储过程并在你的sql server中安排根据你的日程安排推入另一个服务器数据库。通过这种方式,您可以通过多种方式控制它。我的意思是控制任何依赖项(表级或业务级别)。
要在t-sql中执行此操作,您可以使用以下系统存储过程来安排每日作业。此示例每天凌晨1:00安排。有关各个存储过程的语法和有效参数范围的详细信息,请参阅Microsoft帮助。
DECLARE @job_name NVARCHAR(128), @description NVARCHAR(512), @owner_login_name NVARCHAR(128), @database_name NVARCHAR(128);
SET @job_name = N'Some Title';
SET @description = N'Periodically do something';
SET @owner_login_name = N'login';
SET @database_name = N'Database_Name';
-- Delete job if it already exists:
IF EXISTS(SELECT job_id FROM msdb.dbo.sysjobs WHERE (name = @job_name))
BEGIN
EXEC msdb.dbo.sp_delete_job
@job_name = @job_name;
END
-- Create the job:
EXEC msdb.dbo.sp_add_job
@job_name=@job_name,
@enabled=1,
@notify_level_eventlog=0,
@notify_level_email=2,
@notify_level_netsend=2,
@notify_level_page=2,
@delete_level=0,
@description=@description,
@category_name=N'[Uncategorized (Local)]',
@owner_login_name=@owner_login_name;
-- Add server:
EXEC msdb.dbo.sp_add_jobserver @job_name=@job_name;
-- Add step to execute SQL:
EXEC msdb.dbo.sp_add_jobstep
@job_name=@job_name,
@step_name=N'Execute SQL',
@step_id=1,
@cmdexec_success_code=0,
@on_success_action=1,
@on_fail_action=2,
@retry_attempts=0,
@retry_interval=0,
@os_run_priority=0,
@subsystem=N'TSQL',
@command=N'EXEC my_stored_procedure; -- OR ANY SQL STATEMENT',
@database_name=@database_name,
@flags=0;
-- Update job to set start step:
EXEC msdb.dbo.sp_update_job
@job_name=@job_name,
@enabled=1,
@start_step_id=1,
@notify_level_eventlog=0,
@notify_level_email=2,
@notify_level_netsend=2,
@notify_level_page=2,
@delete_level=0,
@description=@description,
@category_name=N'[Uncategorized (Local)]',
@owner_login_name=@owner_login_name,
@notify_email_operator_name=N'',
@notify_netsend_operator_name=N'',
@notify_page_operator_name=N'';
-- Schedule job:
EXEC msdb.dbo.sp_add_jobschedule
@job_name=@job_name,
@name=N'Daily',
@enabled=1,
@freq_type=4,
@freq_interval=1,
@freq_subday_type=1,
@freq_subday_interval=0,
@freq_relative_interval=0,
@freq_recurrence_factor=1,
@active_start_date=20170101, --YYYYMMDD
@active_end_date=99991231, --YYYYMMDD (this represents no end date)
@active_start_time=010000, --HHMMSS
@active_end_time=235959; --HHMMSS
如果您需要更多详细信息,请与我们联系。
谢谢, 阿燕