How to Add a Set of Keys (UniqueIDs) to a Temp table to later INSERT into Production Table

[亡魂溺海] 提交于 2020-06-17 09:54:30

问题


I have the data ready to Insert into my Production table however the ID column is NULL and that needs to be pre-populated with the IDs prior to Insert. I have these IDs in another Temp Table... all I want is to simply apply these IDs to the records in my Temp Table.

For example... Say I have 10 records all simply needing IDs. I have in another temp table exactly 10 IDs... they simply need to be applied to my 10 records in my 'Ready to INSERT' Temp Table.

I worked in Oracle for about 9 years and I would have done this simply by looping over my 'Collection' using a FORALL Loop... basically I would simply loop over my 'Ready to INSERT' temp table and for each row apply the ID from my other 'Collection'... in SQL Server I'm working with Temp Tables NOT Collections and well... there's no FORALL Loop or really any fancy loops in SQL Server other than WHILE.

My goal is to know the appropriate method to accomplish this in SQL Server. I have learned that in the SQL Server world so many of the DML operations are all SET Based whereas when I worked in oracle we handled data via arrays/collections and using CURSORS or LOOPs we would simply iterate thru the data. I've seen in the SQL Server world using CURSORS and/or iterating thru data record by record is frowned upon.

Help me get my head out of the 'Oracle' space I was in for so long and into the 'SQL Server' space I need to be in. This has been a slight struggle.

The code below is how I've currently implemented this however it just seems convoluted.

    SET NOCOUNT ON;

    DECLARE @KeyValueNewMAX INT,
            @KeyValueINuse  INT,
            @ClientID       INT,
            @Count          INT;

    DROP TABLE IF EXISTS #InterOtherSourceData;
    DROP TABLE IF EXISTS #InterOtherActual;
    DROP TABLE IF EXISTS #InterOtherIDs;

    CREATE TABLE #InterOtherSourceData      -- Data stored here for DML until data is ready for INSERT 
    (
        UniqueID            INT IDENTITY( 1, 1 ),
        NewIntOtherID       INT,
        ClientID            INT
    );

    CREATE TABLE #InterOtherActual          -- Prod Table where the data will be INSERTED Into
    (
        IntOtherID          INT,
        ClientID            INT
    );

    CREATE TABLE #InterOtherIDs             -- Store IDs needing to be applied to Data
    (
        UniqueID            INT IDENTITY( 1, 1 ),
        NewIntOtherID       INT
    );

    BEGIN

        /* TEST Create Fake Data and store it in temp table */
            WITH fakeIntOtherRecs AS
            (
                SELECT 1001 AS ClientID, 'Jake'  AS fName, 'Jilly'   AS lName UNION ALL
                SELECT 2002 AS ClientID, 'Jason' AS fName, 'Bateman' AS lName UNION ALL
                SELECT 3003 AS ClientID, 'Brain' AS fName, 'Man'     AS lName 
            )

            INSERT INTO #InterOtherSourceData (ClientID)
            SELECT fc.ClientID--, fc.fName, fc.lName
            FROM fakeIntOtherRecs fc
            ;
        /* END TEST Prep Fake Data */


        /* Obtain count so we know how many IDs we need to create */
        SELECT @Count = COUNT(*) FROM #InterOtherSourceData;

        PRINT 'Count: ' + CAST(@Count AS VARCHAR);

        /* For testing set value OF KeyValuePre to the max key currently in use by Table */
        SELECT @KeyValueINuse = 13;

        /* Using the @Count let's obtain the new MAX ID... basically Existing_Key + SourceRecordCount = New_MaxKey */
        SELECT @KeyValueNewMAX = @KeyValueINuse + @Count /* STORE new MAX ID in variable */

        /* Print both keys for testing purposes to review */
        PRINT 'KeyValue Current: ' + CAST(@KeyValueINuse AS VARCHAR) + ' KeyValue Max: ' + CAST(@KeyValueNewMAX AS VARCHAR);

        /* Using recursive CTE generate a fake table containing all of the IDs we want to INSERT into Prod Table */
        WITH CTE AS
        (
            SELECT (@KeyValueNewMAX - @Count) + 1 AS STARTMINID, @KeyValueNewMAX AS ENDMAXID  UNION ALL

            /* SELECT FROM CTE to create Recursion */
            SELECT STARTMINID + 1  AS STARTMINID, ENDMAXID FROM CTE 
            WHERE (STARTMINID + 1) < (@KeyValueNewMAX + 1)
        )




        INSERT INTO #InterOtherIDs (NewIntOtherID)
        SELECT c.STARTMINID AS NewIntOtherID
        FROM CTE c
        ;



        /* Apply New IDs : Using the IDENTITY fields on both Temp Tables I can JOIN the tables by the IDENTITY columns
            | Is there a BETTER Way to do this?... like LOOP over each record rather than having to build up common IDs in both tables using IDENTITY columns?
        */
        UPDATE #InterOtherSourceData SET NewIntOtherID = oi.NewIntOtherID
        FROM #InterOtherIDs oi
            JOIN #InterOtherSourceData o ON o.UniqueID = oi.UniqueID
        ;

        /* View data that is ready for insert */
        --SELECT *
        --FROM #InterOtherSourceData
        --;

        /* INSERT DATA INTO PRODUCTION TABLE */
        INSERT INTO #InterOtherActual (IntOtherID, ClientId)
        SELECT NewIntOtherID, ClientID
        FROM #InterOtherSourceData
        ;

        SELECT * FROM #InterOtherActual;
    END

回答1:


To pre-generate key values in SQL Server use a sequence rather than an IDENTITY column.

eg

drop table if exists t
drop table if exists #t_stg 

drop sequence t_seq

go
create sequence t_seq start with 1 increment by 1

create table t(id int primary key default (next value for t_seq),a int, b int)

create table #t_stg(id int, a int, b int)

insert into #t_stg(a,b) values (1,2),(3,3),(4,5)

update #t_stg set id = next value for t_seq

--select * from #t_stg

insert into t(id,a,b) 
select * from #t_stg 


来源:https://stackoverflow.com/questions/62313315/how-to-add-a-set-of-keys-uniqueids-to-a-temp-table-to-later-insert-into-produc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!