根据更新列表(表)插入表

时间:2018-08-18 21:28:13

标签: sql-server

我已经为此苦苦挣扎了一段时间,并感谢任何帮助。 我有一个不断更新的表,该表的表名列表(同一表可能会出现多次)最近已在数据库1中用新数据更新过。

我想创建一个查询,该查询检查此更新列表,并将数据库1中更新后的表中的数据插入数据库2中的相应表中,并一直循环到列表末尾。 < / p>

列表如下所示:

ID                          Table         TimeStamp   
-----------------------     --------      -----------------------
0313778E-CB68-E811-910D     Customer      2018-07-10 13:27:28.567  
0313778E-CB68-E811-910D     Customer      2018-07-10 13:28:58.010  
194DD17A-CE68-E811-910D     Order         2018-07-10 13:27:28.567   
0EBB391D-126B-E811-910D     Product       2018-07-10 13:28:58.010      
4AAE33A5-CE68-E811-910D     Customer      2018-07-10 13:27:28.567     
DFA2A68C-056B-E811-910D     Order         2018-07-10 13:28:58.010     
C2CFECB6-CE68-E811-910D     Employee      2018-07-10 13:27:28.583

更糟糕的是,数据库2中的表没有与数据库1相同的列数。 我一直在研究MERGE和Cursor以及动态SQL。我对这些是新手,请继续使用。我认为动态SQL + CURSOR是最好的方法。所有这些将导致存储过程。也许有更好的方法吗?无论如何,这就是我所拥有的:

Declare @Source_TableName_Column --this one contains the Database 1 tables as well as the correct columns needed to fill matching table in Database 2.
Declare @InsertInto NVARCHAR(MAX), 
@TargetTable NVARCHAR(MAX)='Select name from Database2.sys.all_objects',   --list of tables I have in Database 2
@Columns NVARCHAR(MAX) = 'Select name from Database2.sys.all_columns',  --list of columns I have in Database 2 (same names as it is in SourceTable in Database 1)
; 

DECLARE TableInsert CURSOR FOR
SELECT distinct SourceTableName from Database3.dbo.UpdateTableList
OPEN TableInsert

FETCH NEXT FROM TableInsert
INTO @TableName

--LOOP
WHILE @@FETCH_STATUS=0
   BEGIN
   SET @InsertInto = 'insert into Database2.dbo.'+@TargetTable+' '+(@Columns)+' values'+(....)+'' --not sure how to do this variable where i get all the results from SourceTable matching columns in TargetTable in database 2

        FETCH NEXT FROM TableInsert
        INTO @TableName       
   END
        --CLOSE CURSOR
        CLOSE TableInsert
        DEALLOCATE TableInsert

2 个答案:

答案 0 :(得分:0)

这很复杂。我将以比您正在做的事情更简单的方式来处理它。如果方案涉及的目标表具有相同的架构,但是包含许多列,那么我将按照您的方式进行操作,看来情况并非如此。 这就是我要做的。

打开cur1 接下来从cur1抓取到@tablename ....

@@ fetchstatus = 0时 开始

如果@@ tablename ='tbl1' 开始  插入到database2.dbo.tbl2值 从database1.dbo.table1中选择...,其中.. 结束

如果@@ tablename ='tblx' 等等

接下来从cur1抓取到... 结束

答案 1 :(得分:0)

我提出了一个对我有用的解决方案。我在这里更改了一些名称,以更好地适应我上面的描述。我认为它们是正确的,以后会仔细检查,如果有错误,请更正=)

我还是不确定代码中后面的delete语句。 我有一个基于更新列表的TempTable。 Ive插入表后,我想删除更新列表中的行。我有一个带有两个“ where字段IN(TempTable中的对应字段)”子句,另一个带有“从...中删除……where存在(tempTable)”子句。Temptable有两列,但更新列表总共有三列。以最快/最好的列为准?

DECLARE @InsertInto NVARCHAR(MAX); 
DECLARE @SourceID NVARCHAR(MAX);
DECLARE @TableAttribute NVARCHAR(MAX);
DECLARE @SourceViewName NVARCHAR(MAX);
DECLARE @TargetTable NVARCHAR(MAX);
DECLARE @SourceTableName NVARCHAR(MAX);

/*-------Create temp table to be used in cursor-------*/
Declare @SQL_TempTable_Insert NVARCHAR(MAX);
    IF OBJECT_ID('tempdb..#Cursor_TempTable') IS NOT NULL DROP TABLE #Cursor_TempTable
    CREATE TABLE #Cursor_TempTable (
    SourceEntity NVARCHAR(MAX)  )

/*-------variable to be used in insert step below-------*/
SET @SQL_TempTable_Insert = 'SELECT SourceLogicalName FROM DataBaseC.dbo.REF_ENTITIES_SYNC group by SourceLogicalName'

/*-------Insert into temp table-------*/
INSERT INTO #Cursor_TempTable EXECUTE (@SQL_TempTable_Insert)



/*-------Create temp table from NeworUpdate table-------*/
Declare @SQL_TempTable_NewOrUpdated NVARCHAR(MAX);
    IF OBJECT_ID('tempdb.. #TempTable_NewOrUpdated') IS NOT NULL DROP TABLE  #TempTable_NewOrUpdated
    CREATE TABLE #TempTable_NewOrUpdated (
    [ID] NVARCHAR(MAX),
    [TimeStamp] DATETIME ) 

/*-------variable to be used in insert step below in NewOrUpdate temp table-------*/
SET @SQL_TempTable_NewOrUpdated = 'SELECT ID, TimeStamp FROM DataBaseC.dbo.[REF_POSTS_NewOrUpdated] group by ID, TimeStamp'

/*-------Insert into NewOrUpdate temp table-------*/
INSERT INTO #TempTable_NewOrUpdated EXECUTE (@SQL_TempTable_NewOrUpdated)




/*-------Cursor segment-------*/
DECLARE EntitiesInsert CURSOR FOR
 SELECT SourceEntity FROM #Cursor_TempTable
OPEN EntitiesInsert
FETCH NEXT FROM EntitiesInsert
INTO @TargetTable 
--LOOP
WHILE @@FETCH_STATUS=0
   BEGIN
    BEGIN TRY
     BEGIN TRAN

SET @SourceViewName = (select SourceName from DataBaseC.dbo.REF_ENTITIES_SYNC where Targetname = @TargetTable);
SET @SourceTableName = (select SourceTableName from DataBaseC.dbo.REF_ENTITIES_SYNC where Targetname = @TargetTable);
SET @TableAttribute = stuff(( select ', ' +char(10)+ ac.[name] from DataBaseB.sys.all_columns ac 
                              inner join DataBaseB.sys.all_objects ao on ao.object_id=ac.object_id
                              where ao.name = @TargetTable and ac.name not in ('ValidFrom','ValidTo')
                              FOR XML PATH('')
                              ), 1, 1, '')

--Finds DatabaseA table's Primary Key 
SET @SourceID =  (select c.name
 from sys.index_columns ic
 inner join sys.columns c on ic.object_id = c.object_id and ic.column_id = c.column_id
 inner join sys.indexes i on ic.object_id = i.object_id and ic.index_id = i.index_id
 inner join sys.tables t on i.object_id = t.object_id
 inner join sys.schemas s on t.schema_id = s.schema_id
 where i.is_primary_key= 1 and t.name = @SourceTableName);

SET @InsertInto = 'INSERT INTO DataBaseB.dbo.'+@TargetTable+' ('+@TableAttribute+') 
SELECT '+@TableAttribute+' FROM DataBaseA.dbo.'+@SourceViewName+'  
where '+@SourceID+' in (select nu.ID from DataBaseC.Inno.REF_ENTITIES_SYNC sync inner join #TempTable_NewOrUpdated nu on nu.SourceEntity = sync.TargetName where sync.TargetName = '''+@TargetTable+''' group by nu.ID )' 
EXEC sp_sqlexec @insertInto


--Delete the records from [DataBaseC].[dbo].[REF_POSTS_NewOrUpdated] that we have inserted.
--DELETE FROM [DataBaseC].[dbo].[REF_POSTS_NewOrUpdated]
--  WHERE ID = (select [ID] from #TempTable_NewOrUpdated)
--  AND TimeStamp = (select [Timestamp] from #TempTable_NewOrUpdated)  
----alt2
--DELETE FROM [DataBaseC].[dbo].[REF_POSTS_NewOrUpdated]
--  where exists (select * from #TempTable_NewOrUpdated)


--End TRAN
  COMMIT
--End TRY
  END TRY

    --Catch possible errors
        BEGIN CATCH

            --IF there is an open transaction then roll back and print error messages.
            IF @@TRANCOUNT > 0
            ROLLBACK TRANSACTION

            DECLARE @ErrorNumber INT = ERROR_NUMBER();
            DECLARE @ErrorLine INT = ERROR_LINE();
            DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE();
            DECLARE @ErrorSeverity INT = ERROR_SEVERITY();
            DECLARE @ErrorState INT = ERROR_STATE();

            PRINT 'Actual error number: ' + CAST(@ErrorNumber AS VARCHAR(10));
            PRINT 'Actual line number: ' + CAST(@ErrorLine AS VARCHAR(10));
            PRINT 'Actual error message: ' + CAST(@ErrorMessage AS VARCHAR(MAX));
            PRINT 'Actual error Severity: ' + CAST(@ErrorSeverity AS VARCHAR(MAX));             
            PRINT 'Actual error State: ' + CAST(@ErrorState AS VARCHAR(MAX));

        END CATCH

FETCH NEXT FROM EntitiesInsert
INTO @TargetTable      
END
CLOSE EntitiesInsert
DEALLOCATE EntitiesInsert

GO