SQL - Copy Data Within Same Table - sql

I'm not that great with SQL Server, but I'm trying to do some behind the scenes work to create some functionality that our EMR system lacks - copying forms (and all their data) between patients.
In SQL Server 2008 R2 I have three tables that deal with these forms that have been filled out:
**Table 1**
encounter_id patient_id date time etc etc etc etc
1234 112233 2014-01-02 14:25:01:00 a b c d
**Table 2**
encounter_id page recorded_on recorded_by etc etc
1234 1 2014-01-02 134 asdf asdf
1234 2 2014-01-02 134 jkl; jkl;
**Table 3**
encounter_id page keyname keyvalue
1234 1 key1 aaa
1234 1 key2 bbb
1234 1 key3 ccc
1234 1 key4 ddd
1234 2 key5 eee
1234 2 key6 fff
1234 2 key7 ggg
As you can see, they all match together with the encounter_id, which is linked to the patient_id (In the first table).
What I'm trying to be able to do is copy all the rows in these three tables for a particular encounter_id back into the same table they come from, but with a different (system generated) encounter_id for a patient_id that I would specify. In essence, copying the form from one patient to another.
Any help on this is greatly appreciated.

I always like creating sample tables in [tempdb] so that the syntax is correct. I created tables [t1], [t2], and [t3]. There are primary and foreign keys.
If you have a well developed schema, ERD (entity relationship diagram) http://en.wikipedia.org/wiki/Entity-relationship_diagram , these relationships should be in place.
-- Playing around
use tempdb
go
--
-- Table 1
--
-- Remove if it exists
if object_id('t1') > 0
drop table t1
go
-- Create the first table
create table t1
(
encounter_id int,
patient_id int,
the_date date,
the_time time,
constraint pk_t1 primary key (encounter_id)
);
go
-- Add one row
insert into t1 values (1234, 112233, '2014-01-02', '14:25:01:00');
go
-- Show the data
select * from t1
go
--
-- Table 2
--
-- Remove if it exists
if object_id('t2') > 0
drop table t2
go
-- Create the second table
create table t2
(
encounter_id int,
the_page int,
recorded_on date,
recorded_by int,
constraint pk_t2 primary key (encounter_id, the_page)
);
go
-- Add two rows
insert into t2 values
(1234, 1, '2014-01-02', 134),
(1234, 2, '2014-01-02', 134);
go
-- Show the data
select * from t2
go
--
-- Table 3
--
-- Remove if it exists
if object_id('t3') > 0
drop table t3
go
-- Create the third table
create table t3
(
encounter_id int,
the_page int,
key_name1 varchar(16),
key_value1 varchar(16),
constraint pk_t3 primary key (encounter_id, the_page, key_name1)
);
go
-- Add seven rows
insert into t3 values
(1234, 1, 'key1', 'aaa'),
(1234, 1, 'key2', 'bbb'),
(1234, 1, 'key3', 'ccc'),
(1234, 1, 'key4', 'ddd'),
(1234, 2, 'key5', 'eee'),
(1234, 2, 'key6', 'fff'),
(1234, 2, 'key7', 'ggg');
go
-- Show the data
select * from t3
go
--
-- Foreign Keys
--
alter table t2 with check
add constraint fk_t2 foreign key (encounter_id)
references t1 (encounter_id);
alter table t3 with check
add constraint fk_t3 foreign key (encounter_id, the_page)
references t2 (encounter_id, the_page);
Here comes the fun part, a stored procedure to duplicate the data.
--
-- Procedure to duplicate one record
--
-- Remove if it exists
if object_id('usp_Duplicate_Data') > 0
drop procedure t1
go
-- Create the procedure
create procedure usp_Duplicate_Data #OldId int, #NewId int
as
begin
-- Duplicate table 1's data
insert into t1
select
#NewId,
patient_id,
the_date,
the_time
from t1
where encounter_id = #OldId;
-- Duplicate table 2's data
insert into t2
select
#NewId,
the_page,
recorded_on,
recorded_by
from t2
where encounter_id = #OldId;
-- Duplicate table 3's data
insert into t3
select
#NewId,
the_page,
key_name1,
key_value1
from t3
where encounter_id = #OldId;
end
Last but not least, we have to call the stored procedure to make sure it works.
-- Sample call
exec usp_Duplicate_Data 1234, 7777
In summary, I did not add any error checking or accounted for a range of Id's. I leave these tasks for you to learn.

Made a little fiddle as an example, here (link)
The solution is perhaps needlessly complex but it offers a good variety of other useful stuff as well, I just wanted to test how to build that dynamically. The script does print out the commands, making it relatively easy to remove the TSQL and just produce the plain-SQL to do as you wish.
What it does, is that it requires an encounter_id, which it will then use to dynamically fetch the columns (with the assumption that encounter_id is the PK for TABLE_1) to insert a new record in TABLE_1, store the inserted.encounter_id value, and use that value to fetch and copy the matching rows from TABLE_2 and TABLE_3.
Basically, as long as the structure is correct (TABLE_1 PK is encounter_id which is an identity type), you should be able to just change the table names referenced in the script and it should work directly regardless of which types of columns (and how many of them) your particular tables have.
The beef of the script is this:
/* Script begins here */
DECLARE #ENCOUNTER_ID INT, #NEWID INT, #SQL VARCHAR(MAX), #COLUMNS VARCHAR(MAX)
IF OBJECT_ID('tempdb..##NEW_ID') IS NOT NULL
DROP TABLE ##NEW_ID
CREATE TABLE ##NEW_ID (ID INT)
/* !!! SET YOUR DESIRED encounter_id RECORDS TO BE COPIED, HERE !!! */
SET #ENCOUNTER_ID = 1234
IF EXISTS (SELECT TOP 1 1 FROM TABLE_1 WHERE encounter_id = #ENCOUNTER_ID)
BEGIN
SELECT #COLUMNS = COALESCE(#COLUMNS+', ', 'SELECT ')+name
FROM sys.columns WHERE OBJECT_NAME(object_id) = 'TABLE_1' AND name <> 'encounter_id'
SET #COLUMNS = 'INSERT INTO TABLE_1 OUTPUT inserted.encounter_id INTO ##NEW_ID '+#COLUMNS+' FROM TABLE_1 WHERE encounter_id = '+CAST(#ENCOUNTER_ID AS VARCHAR(25))
EXEC(#COLUMNS)
PRINT(#COLUMNS)
SELECT TOP 1 #NEWID = ID, #COLUMNS = NULL FROM ##NEW_ID
SELECT #COLUMNS = COALESCE(#COLUMNS+', ', '')+name
FROM sys.columns WHERE OBJECT_NAME(object_id) = 'TABLE_2'
SET #COLUMNS = 'INSERT INTO TABLE_2 ('+#COLUMNS+') SELECT '+REPLACE(#COLUMNS,'encounter_id',''+CAST(#NEWID AS VARCHAR(25))+'')
+' FROM TABLE_2 WHERE encounter_id = '+CAST(#ENCOUNTER_ID AS VARCHAR(25))
EXEC(#COLUMNS)
PRINT(#COLUMNS)
SET #COLUMNS = NULL
SELECT #COLUMNS = COALESCE(#COLUMNS+', ', '')+name
FROM sys.columns WHERE OBJECT_NAME(object_id) = 'TABLE_3'
SET #COLUMNS = 'INSERT INTO TABLE_3 ('+#COLUMNS+') SELECT '+REPLACE(#COLUMNS,'encounter_id',''+CAST(#NEWID AS VARCHAR(25))+'')
+' FROM TABLE_3 WHERE encounter_id = '+CAST(#ENCOUNTER_ID AS VARCHAR(25))
EXEC(#COLUMNS)
PRINT(#COLUMNS)
IF OBJECT_ID('tempdb..##NEW_ID') IS NOT NULL
DROP TABLE ##NEW_ID
END

declare #oldEncounterID int
set #oldEncounterID = 1234
declare #newEncounterID int
set #newEncounterID = 2345
insert into table1(encounter_id, patient_id, date, time, etc)
select newEncounterID, patient_id, date, time, etc
from table1 where encounter_id = oldEncounterID
and so on... problem with this approach you must know in advantage what all the columns are, and if they change you may change the columns accordingly
Another approach:
declare #oldEncounterID int
set #oldEncounterID = 1234
declare #newEncounterID int
set #newEncounterID = 2345
select * into #table1 from table1 where encounter_id = oldEncounterID
update #table1 set encounter_id = newEncounterID
insert into table1 select * from #table1
and so on... this second approach however may need a little adjustment if there is an identity column then you'll have to set identity_insert to on

Psuedo code, not tested:
DECLARE #patient_id INT, #date datetime, #time ??
SET #patient_id = 112244 --your patient id
INSERT INTO [**Table 1**] (patient_id, date, time, etc, etc, etc, etc)
VALUES (#patient_id, #date, #time, 'a', 'b', 'c', 'd')
DECLARE #encounter_id int
SET #encounter_id = SCOPE_IDENTITY -- or select #encounter_id = encounter_id from [**Table 1**] where patientId = #patient_id
INSERT INTO [**Table 2**] (encounter_id, page, recorded_on, recorded_by, etc, etc2)
SELECT #encounter_id, page, recorded_on, recorded_by, etc, etc2
FROM [**Table 2**]
WHERE encounter_id = 1234
INSERT INTO [**Table 3**] (encounter_id, page, keyname, keyvalue)
SELECT #encounter_id, page, keyname, keyvalue
FROM [**Table 3**]
WHERE encounter_id = 1234

Related

SQL Server 2008: Sql Insert/Update into another table using insertion IDs output from another table

I have a procedure for insert in multiple dependent tables (update in case record exist). I have input parameters as comma separated string which I am reading in table.
After 1st insertion I am getting InsertedIds in another table variable.
I am struggling over how to do insert in 2nd table. I have following input parameters for 2nd table:
Declare #IdsToBeUpdated table (primary key identity pkey, id int) -- values are 1,-1,3,-1
Declare #CommentsTobeInserted table( primary key identity pkey, comment varchar (max)) -- values are 'com1', 'com2', 'com3'
-1 input in table #IdsToBeUpdated depicts insertion for the corresponding rows in all input tables and value other than -1 depicts that records at that pkey value in all other tables (#CommentsTobeInserted table as in example) have to be updated.
So after first insertion I am getting the inserted ids for rows with -1 value. #InsertedIds = 4,5
So my Ids list logically would become.. 1,4,3,5.
But I am stuck now how to insert/update records in second table respectively.
2nd table would be like follows:
Pkey Primary key identity, commentIds(coming from inserted ids and #IdsToBeUpdated), comments.
I have added one more InsertedIds column in #CommentsTobeInserted. If I could fill it with right InsertedId against correct row, I guess I would be able to do insert/update in 2nd table. And where the value is Id in new column I would do insert, where it's null, I would perform update using #IdsToBeUpdated table.
But currently none of my approach is working. I am new to SQL. Any help would be highly appreciated.
Following is some portion of script for better understanding. I have added first insertion script as well.
USE [Demo]
GO
/****** Object: StoredProcedure [dbo].[USP_NewRequest_Insert] Script Date: 2/11/2016 2:50:34 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[USP_NewRequest_Insert]
-----------------------------------
--------- SomeInput parameters
---------for first insertion omitted
--------------------------------
#IdsToBeUpdated varchar(MAX), --Values are 23|-1|32|-1|-1
#CommentList AS VARCHAR(MAX), --Values 'C2'|'C4'|'C5'|'C6'|'C7'
#MCodeList VARCHAR(MAX), --Values 'M2'|'M4'|'M5'|'M6'|'M7'
#CustomerIdsList VARCHAR(MAX), ----Values 'Cust2'|'Cust4'|'Cust5'|'Cust6'|'Cust7'
#ReturnValue AS INT OUTPUT,
------------------Data is in the order it has to be inserted.. where IDs exist in #IdsToBeUpdated, updation would be done. For -1 values, insertion.
AS
BEGIN
BEGIN TRANSACTION
--------------------------Split input strings aand insert in Table variable----------------------------
declare #MCodes Table (pkey int primary key identity, MCode varchar(20))
insert into #MCodes select s.Item from [dbo].UDF_SplitString(#MCodeList, '|') s
declare #CusCodes Table (pkey int primary key identity, CusCode varchar(200))
insert into #CusCodes select s.Item from [dbo].UDF_SplitString(#CustomerIdsList, '|') s
declare #ReqDetailsIds Table (pkey int primary key identity, Id Int)
insert into #ReqDetailsIds select Convert(INT,RTRIM(LTRIM(s.Item))) from [dbo].UDF_SplitString(#IdsToBeUpdated, '|') s
where s.Item is not null and RTRIM(LTRIM(s.Item)) <>''
declare #ProductComments Table (pkey int primary key identity, Comment Varchar(max), insertedId int null)
insert into #ProductComments(Comment) select s.Item from [dbo].UDF_SplitString(#CommentList, '|') s
DECLARE #intErrorCode int;
------------------------------------------------------------------------------------------------------------
-----------------First Insertion which returns inserted IDs for 2nd insertion
------------------------------------------------------------------------------------------------------------------
---Insert/Update product details in [RequestDetails]
Declare #InsertedIDList Table (pkey int primary key identity, ID int); --------Table to read inserted Ids. Used in query below
-----------------------Insert query in case Detail id = -1
INSERT INTO [dbo].[RequestDetails]
[MCode]
,[CustomerIds]
,[ExpectedVolume]------Some parameters coming for first insertion in input
,[StatusCode])
Output INSERTED.ReqDetailId Into #InsertedIDList(ID)
SELECT A.MCode, B.CusCode, E.Vol,1
FROM #MCodes A
JOIN #CusCodes B ON B.pkey = A.pkey
JOIN #ExpectedVols E ON E.pkey = A.pkey
JOIN #ReqDetailsIds G ON G.pkey = A.pkey
WHERE G.Id = -1 --If id = -1, insert
---------------------------Update Query for rest records
UPDATE [dbo].[RequestDetails]
SET [MCode] = upd.MCode
,[CustomerIds] = upd.CusCode
,[ExpectedVolume] = upd.ExVol
,[StatusCode] = 1
FROM(
SELECT A.MCode, B.CusCode, E.ExVol, G.Id
FROM #MCodes A
JOIN #CusCodes B ON B.pkey = A.pkey
JOIN #ExpectedVols E ON E.pkey = A.pkey
JOIN #ReqDetailsIds G ON G.pkey = A.pkey
WHERE G.Id <> -1
) upd
WHERE upd.Id = dbo.RequestDetails.ReqDetailId
IF(##Error<>0)
BEGIN
SET #intErrorCode = ##Error
GOTO ERROR
END
ELSE
BEGIN
SET #ReturnValue=1
END
---------------------------------------------------------------------------
----------------------------Now similarly I have to do insert/update in Comments Table. But
----------------------------Comments table has RequestDetails Id column as foreign key. So
----------------------------now the challange is to add the rows with Inserted ID where value was = -1
----------------------------in input. We have got the IDs corresponding to -1 values from above insertion
----------------------------in the #InsertedIDList Table variable
-----------------------------------------------------------------------------------------
----------------------------Following is what I have tried so far. But I am not able to insert
----------------------------correct InsertedId against correct record.
----------------------------------------------------------------------------------------
-----------------------Here I tried to insert the new generated ids against corresponding comments in table variable.
-----------------------So that I can perform insert where value is not null. As NULL would be inserted where new ID has not been created
-----------------------and corresponding updated ID exists in input (Values not equal to -1)
-------------------------------------------------------------------------------------------------
Update #ProductComments set insertedId = i.ID from ---------This query is not working
(select A.pkey, B.id as detailId, row_number() over (order by (select 0)) as row_num from
#ProductComments A
JOIN #ReqDetailsIds B ON B.pkey = A.pkey) as mappedNewIds right join
#InsertedIDList i on i.pkey = mappedNewIds.row_num
where mappedNewIds.pkey = [#ProductComments].pkey
----Insert in CommentsTable for New Comments against request
---------------------------------
INSERT INTO [dbo].CommentsTable
( ReqDetailId, Comments, CreatedOn )
SELECT A.insertedId, A.Comment, GETDATE()
FROM #ProductComments A
where A.insertedId is not null
-----Update Query
------------------------------------------------------------------------------------------
UPDATE [dbo].[CommentsTable]
SET [ReqDetailId] = upd.Id
,[Comments] = upd.Comment
,[CreatedOn] = GetDate()
FROM(
SELECT A.Comment, B.Id
FROM #ProductComments A
JOIN #ReqDetailsIds B ON B.pkey = A.pkey
WHERE A.insertedId is not null
) upd
WHERE upd.Id = dbo.CommentsTable.ReqDetailId
END
select * from CommentsTable;
---------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
IF(##Error<>0)
BEGIN
SET #intErrorCode = ##Error
GOTO ERROR
END
ELSE
BEGIN
SET #ReturnValue=1
END
COMMIT TRANSACTION
ERROR:
IF (#intErrorCode <> 0) BEGIN
SET #ReturnValue = 0;
ROLLBACK TRANSACTION
END
END

Fill automatic data in second table when insert data in one table

I have two table Table1 and Table2 and structure of table as
Table1
Primary Key | Name
Table2
Primary Key | Table1_Id_pk | Status - true/false value
When I insert data into Table2 I want to automatically transfer that data in table1 from Table2 which have Status false.
You can create AFTER INSERT trigger:
CREATE TRIGGER DataMigration
ON Table2
AFTER INSERT
AS
BEGIN
INSERT INTO Table1
SELECT *
FROM TAble2
WHERe Status = 'false'
END
GO
Check this example, use ##identity to get inserted row-id and use that id for child table.
declare #t1 table (pk int identity(1,1) not null , name varchar(50) )
declare #t2 table (pk int identity(1,1) not null , t1pk int, status bit )
declare #new_table1Id int
insert into #t1 values( 'ajay')
set #new_table1Id = ##IDENTITY -This gives you last inserted id of #t1
insert into #t2 values( #new_table1Id , 0)
select * from #t1
select * from #t2
##IDENTITY official documentation

Conversion failed when converting the varchar value to data type int while incrementing

Was wondering if you can correct my syntax.
update TestTable
set test_person = CAST(test_person as Varchar = 'TEST' (50)) + 1
Im trying to update all columns in a table and increment it by 1 (hence the cast since the column is a string).
T-SQL
DECLARE #counter INT = 0
UPDATE TestTable
SET test_person = 'Test' + CAST(#counter AS VARCHAR(16)), #counter = #counter + 1
Something I've done in the past to do incrementing values in a string column is something like this:
http://sqlfiddle.com/#!6/7f0f5/2
create table testTable (id int primary key identity(1,1), test_person varchar(100))
insert into testTable (test_person)
select 'bob loblaw'
union all select 'Buster Bluth'
union all select 'Jason Bateman'
union all select 'gob'
union all select 'Lucille #2'
update testTable
set test_person = 'test ' + convert(varchar(30), id)
select * from testTable
results:
ID TEST_PERSON
1 test 1
2 test 2
3 test 3
4 test 4
5 test 5
note this works when your table has an identity primary key. You did not give your entire table schema, but if it does not have this identity primary key you could do something similar by creating a temp/variable table to hold your data that does have an int primary key to do the same thing.
Another option would be to use a loop/cursor to do your population... but that's kind of a pain to write.
Another option would be to use ROW_NUMBER which is sql server (not sure about others). Without the full table schema i can only give an example of how to accomplish:
seen in fiddle: http://sqlfiddle.com/#!6/7f0f5/5
update testTable
set test_person = 'test ' + convert(varchar(30), rowNum)
from testTable
inner join (
-- create an incrementing number for each row
select row_number() over(order by test_person) as rowNum, test_person
from testTable
) rows on testTable.test_person = rows.test_person
select * from testTable

Insert - Select keeping identity mapping

I have 2 tables, and im trying to insert data from one to another and keepeng the mappings between ids.
I found here someone with the same problem, but the solution isnt good for me.
here is the example:
the two tables
CREATE TABLE [source] (i INT identity PRIMARY KEY, some_value VARCHAR(30))
CREATE TABLE [destination] (i INT identity PRIMARY KEY, some_value VARCHAR(30))
CREATE TABLE [mapping] (i_old INT, i_new INT) -- i_old is source.i value, i_new is the inserted destination.i column
some sample data
INSERT INTO [source] (some_value)
SELECT TOP 30 name
FROM sysobjects
INSERT INTO [destination] (some_value)
SELECT TOP 30 name
FROM sysobjects
Here, i want to transfer everything from source into destination, but be able to keep a mapping on the two tables:
I try to use OUTPUT clause, but i cannot refer to columns outside of the ones being inserted:
INSERT INTO [destination] (some_value)
--OUTPUT inserted.i, s.i INTO [mapping] (i_new, i_old) --s.i doesn't work
SELECT some_value
FROM [source] s
Anyone has a solution for this?
Not sure is it write way but it works :D
MERGE [#destination] AS D
USING [#source] AS s
ON s.i <> s.i
WHEN NOT MATCHED BY TARGET
THEN
INSERT (some_value) VALUES (some_value)
OUTPUT inserted.i, s.i INTO [#mapping] (i_new, i_old);
try this sql below if you don't have permission to modify the tables:
The idea is using a temp table to be a bridge between destination table and the mapping table.
SQL Query:
declare #source table (i INT identity PRIMARY KEY, some_value VARCHAR(30))
declare #destination table (i INT identity PRIMARY KEY, some_value VARCHAR(30))
declare #mapping table (i_old INT, i_new INT) -- i_old is source.i value, i_new is the inserted destination.i column
declare #tempSource table
(
id_source INT identity , source_value VARCHAR(30)
,Id_New int,source_new VARCHAR(30)
)
insert into #source
output inserted.i, inserted.some_value into #tempSource(id_source,source_value)
SELECT TOP 10 name
FROM sysobjects
--select * from #tempsource
insert into #destination
OUTPUT inserted.i, inserted.some_value INTO #tempSource (Id_New,source_new)
select source_value from #tempSource
insert into #mapping
select Id_source, Id_New from
(
select a.id_source, a.source_value
from
#tempSource a
where id_source is not null and source_value is not null
) aa
inner join
(
select a.Id_New, a.source_new
from
#tempSource a
where Id_New is not null and source_new is not null
) bb on aa.source_value = bb.source_new
select * from #mapping
The mapping table result:
i_old i_new
----------- -----------
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10

insert data into several tables

Let us say I have a table (everything is very much simplified):
create table OriginalData (
ItemName NVARCHAR(255) not null
)
And I would like to insert its data (set based!) into two tables which model inheritance
create table Statements (
Id int IDENTITY NOT NULL,
ProposalDateTime DATETIME null
)
create table Items (
StatementFk INT not null,
ItemName NVARCHAR(255) null,
primary key (StatementFk)
)
Statements is the parent table and Items is the child table. I have no problem doing this with one row which involves the use of IDENT_CURRENT but I have no idea how to do this set based (i.e. enter several rows into both tables).
Thanks.
Best wishes,
Christian
Another possible method that would prevent the use of cursors, which is generally not a best practice for SQL, is listed below... It uses the OUTPUT clause to capture the insert results from the one table to be used in the insert to the second table.
Note this example makes one assumption in the fact that I moved your IDENTITY column to the Items table. I believe that would be acceptable, atleast based on your original table layout, since the primary key of that table is the StatementFK column.
Note this example code was tested via SQL 2005...
IF OBJECT_ID('tempdb..#OriginalData') IS NOT NULL
DROP TABLE #OriginalData
IF OBJECT_ID('tempdb..#Statements') IS NOT NULL
DROP TABLE #Statements
IF OBJECT_ID('tempdb..#Items') IS NOT NULL
DROP TABLE #Items
create table #OriginalData
( ItemName NVARCHAR(255) not null )
create table #Statements
( Id int NOT NULL,
ProposalDateTime DATETIME null )
create table #Items
( StatementFk INT IDENTITY not null,
ItemName NVARCHAR(255) null,
primary key (StatementFk) )
INSERT INTO #OriginalData
( ItemName )
SELECT 'Shirt'
UNION ALL SELECT 'Pants'
UNION ALL SELECT 'Socks'
UNION ALL SELECT 'Shoes'
UNION ALL SELECT 'Hat'
DECLARE #myTableVar table
( StatementFk int,
ItemName nvarchar(255) )
INSERT INTO #Items
( ItemName )
OUTPUT INSERTED.StatementFk, INSERTED.ItemName
INTO #myTableVar
SELECT ItemName
FROM #OriginalData
INSERT INTO #Statements
( ID, ProposalDateTime )
SELECT
StatementFK, getdate()
FROM #myTableVar
You will need to write an ETL process to do this. You may want to look into SSIS.
This also can be done with t-sql and possibly temp tables. You may need to store unique key from OriginalTable in Statements table and then when you are inserting Items - join OriginalTable with Statements on that unique key to get the ID.
I don't think you could do it in one chunk but you could certainly do it with a cursor loop
DECLARE #bla char(10)
DECLARE #ID int
DECLARE c1 CURSOR
FOR
SELECT bla
FROM OriginalData
OPEN c1
FETCH NEXT FROM c1
INTO #bla
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO Statements(ProposalDateTime) VALUES('SomeDate')
SET #ID = SCOPE_IDENTITY()
INSERT INTO Items(StateMentFK,ItemNAme) VALUES(#ID,#bla)
FETCH NEXT FROM c1
INTO #bla
END
CLOSE c1
DEALLOCATE c1