Solved

SQL 2008R2:  Looking for a fast way to do a 'INSERT INTO target <all columns except two> SELECT <all columns> FROM source'

Posted on 2014-12-04
8
185 Views
Last Modified: 2014-12-04
Hi All

I'm doing a SQL-to-SQL conversion, and have 50+ tables to convert from old (source) to new (target) database.   I think the answer is 'there's no really fast way to do this', but I'll ask the question anyways.

Each 'group' has..
Two Source tables:  Anywhere from 10 to 700 columns.  
   These two tables have the same schema, although some columns have different collations.
Target tables:  Number of columns = Columns in source tables + 2, as I added start_dt and end_dt.

I can't do a 'INSERT INTO Target SELECT * FROM Source' because of the two extra columns.

Question:  What's the fastest way to do a  'INSERT INTO target <all columns except two> SELECT <all columns> FROM source'?

Using a view in the designer I don't see a way to select all and have it show all columns, and then just remove the two I don't need.  * displays as * instead of all column names.

I'll entertain third party apps on this one.

Thanks.
Jim
0
Comment
Question by:Jim Horn
  • 3
  • 3
  • 2
8 Comments
 
LVL 51

Expert Comment

by:HainKurt
ID: 40480892
I can't do a 'INSERT INTO Target SELECT * FROM Source' because of the two extra columns.

you can! if you do this:

INSERT INTO Target SELECT s.*, null, null FROM Source s

or

INSERT INTO Target SELECT s.*, getdate(), getdate() FROM Source s
0
 
LVL 65

Author Comment

by:Jim Horn
ID: 40480896
typo, corrected in the original question, and the position of the start_dt and end_dt columns are the third and fourth column, not at the end.
0
 
LVL 51

Expert Comment

by:HainKurt
ID: 40480911
:)

insert into target (col1, col2, ... , coln) select (col1, col2, null, null, col3, ... , coln) from source

and getting column names should not be so difficult, right click, design, select all columns, copy & paste into your sql
0
Simplifying Server Workload Migrations

This use case outlines the migration challenges that organizations face and how the Acronis AnyData Engine supports physical-to-physical (P2P), physical-to-virtual (P2V), virtual to physical (V2P), and cross-virtual (V2V) migration scenarios to address these challenges.

 
LVL 65

Author Comment

by:Jim Horn
ID: 40480917
Correct, although my question asks if there's a more automated solution, as I'd rather avoid that as some of these tables have 700+ columns.
0
 
LVL 51

Expert Comment

by:HainKurt
ID: 40480924
or drop those two columns from target

do insert into target select * from source

then add those 2 columns at the end (or you can insert those columns in 3rd&4th position)
or add them to the end and then use design table to move those columns to the proper location (why do you need those ones in 3rd & 4th position, and why not the end?)
0
 
LVL 69

Accepted Solution

by:
Scott Pletcher earned 500 total points
ID: 40481087
If the table names match, something like below.  If not, we can join on relative column #, with offsets for the 2 extra columns.  May need some tweaking but you should be able to gen the code pretty quickly for all tables, then run it as needed:


DECLARE @source_table sysname
DECLARE @target_table sysname
DECLARE @col_list varchar(max)
DECLARE @sql varchar(max)

--naturally replaced by cursor table loop in final code
SET @source_table = 'dbs'
SET @target_table = 'dbs'

SELECT @col_list = STUFF((
    SELECT ', ' + src.name
    FROM sys.columns src
    INNER JOIN sys.columns trg ON
        trg.name = src.name
    WHERE
        src.object_id = OBJECT_ID(@source_table) AND
        trg.object_id = OBJECT_ID(@target_table)
    ORDER BY src.column_id
    FOR XML PATH('')
    ), 1, 1, '')

SET @sql = 'INSERT INTO ' + @target_table + ' ( ' + @col_list + ' ) SELECT ' + @col_list + ' FROM ' + @source_table + ' '
PRINT @sql
--EXEC (@sql)
0
 
LVL 65

Author Closing Comment

by:Jim Horn
ID: 40481453
Thanks Scott.  Ran like a champ..

Of the two source tables the second one was the same name as the first + a _History suffix, so I was able to do the below to populate in one run
SET @sql = 'INSERT INTO ' + @target_table + ' ( ' + @col_list + ' ) SELECT ' + @col_list + ' FROM ' + @source_table + ' '
EXEC (@sql) 

SET @sql = 'INSERT INTO ' + @target_table + ' ( ' + @col_list + ' ) SELECT ' + @col_list + ' FROM ' + @source_table + '_History '
EXEC (@sql) 

Open in new window


Then for each target table I ran the below to eliminate any duplicates
;WITH cte as (
 SELECT id, SystemModstamp, ROW_NUMBER() OVER (PARTITION BY id ORDER BY (SELECT 0)) as row_number
 FROM SF_Market) 
DELETE FROM cte WHERE row_number > 1

Open in new window

0
 
LVL 69

Expert Comment

by:Scott Pletcher
ID: 40481456
CORRECTION to wording; instead of: "If the table names match, ...", it should be:
If the COLUMN names match, ...
0

Featured Post

Comprehensive Backup Solutions for Microsoft

Acronis protects the complete Microsoft technology stack: Windows Server, Windows PC, laptop and Surface data; Microsoft business applications; Microsoft Hyper-V; Azure VMs; Microsoft Windows Server 2016; Microsoft Exchange 2016 and SQL Server 2016.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article explains how to reset the password of the sa account on a Microsoft SQL Server.  The steps in this article work in SQL 2005, 2008, 2008 R2, 2012, 2014 and 2016.
Ever needed a SQL 2008 Database replicated/mirrored/log shipped on another server but you can't take the downtime inflicted by initial snapshot or disconnect while T-logs are restored or mirror applied? You can use SQL Server Initialize from Backup…
This videos aims to give the viewer a basic demonstration of how a user can query current session information by using the SYS_CONTEXT function
Via a live example, show how to setup several different housekeeping processes for a SQL Server.

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question