Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replacement for "select * into" in sql azure?

I need a way to generically take a table and copy its data into a new table--basically the same thing that SELECT * INTO does in regular SQL Server. Is there a way to do this in SQL Azure? I only have the existing and new table names at this point.

like image 571
afeygin Avatar asked Aug 01 '12 16:08

afeygin


People also ask

What does select * into in SQL?

The SELECT INTO command copies data from one table and inserts it into a new table.

Which is faster insert into or select into?

INTO' creates the destination table, it exclusively owns that table and is quicker compared to the 'INSERT … SELECT'. Because the 'INSERT … SELECT' inserts data into an existing table, it is slower and requires more resources due to the higher number of logical reads and greater transaction log usage.

What is difference between select into and insert into?

INSERT INTO SELECT vs SELECT INTO: Both the statements could be used to copy data from one table to another. But INSERT INTO SELECT could be used only if the target table exists whereas SELECT INTO statement could be used even if the target table doesn't exist as it creates the target table if it doesn't exist.


2 Answers

I encountered the same problem and the author's answer is not very detailed, so I will give some more information, on how i solved it.

I needed to duplicate tables that start with a given prefix ('from_') into new tables with prefix ('to_').

Generate CREATE Statement

I use this query (found on stackoverflow) to generate all CREATE statements, for every table that starts with 'from_' prefix.


select  'create table [' + so.name + '] (' + o.list + ')' + CASE WHEN tc.Constraint_Name IS NULL THEN '' ELSE 'ALTER TABLE ' + so.Name + ' ADD CONSTRAINT ' + tc.Constraint_Name  + ' PRIMARY KEY ' + ' (' + LEFT(j.List, Len(j.List)-1) + ')' END as query
OBJECTPROPERTY(object_id(TABLE_NAME), 'TableHasIdentity') as tablehasidentity
from    sysobjects so
cross apply
    (SELECT 
        '  ['+column_name+'] ' + 
        data_type + case data_type
            when 'sql_variant' then ''
            when 'text' then ''
            when 'ntext' then ''
            when 'decimal' then '(' + cast(numeric_precision as varchar) + ', ' + cast(numeric_scale as varchar) + ')'
            else coalesce('('+case when character_maximum_length = -1 then 'MAX' else cast(character_maximum_length as varchar) end +')','') end + ' ' +
        case when exists ( 
        select id from syscolumns
        where object_name(id)=so.name
        and name=column_name
        and columnproperty(id,name,'IsIdentity') = 1 
        ) then
        'IDENTITY(' + 
        cast(ident_seed(so.name) as varchar) + ',' + 
        cast(ident_incr(so.name) as varchar) + ')'
        else ''
        end + ' ' +
         (case when IS_NULLABLE = 'No' then 'NOT ' else '' end ) + 'NULL ' + 
          case when information_schema.columns.COLUMN_DEFAULT IS NOT NULL THEN 'DEFAULT '+ information_schema.columns.COLUMN_DEFAULT ELSE '' END + ', ' 

     from information_schema.columns where table_name = so.name
     order by ordinal_position
    FOR XML PATH('')) o (list)
left join
    information_schema.table_constraints tc
on  tc.Table_name       = so.Name
AND tc.Constraint_Type  = 'PRIMARY KEY'
cross apply
    (select '[' + Column_Name + '], '
     FROM   information_schema.key_column_usage kcu
     WHERE  kcu.Constraint_Name = tc.Constraint_Name
     ORDER BY
        ORDINAL_POSITION
     FOR XML PATH('')) j (list)
where   xtype = 'U'
AND name    NOT IN ('dtproperties') AND name like 'from_%'

This query results in a set of values:

['query'] = create table [from_users_roles] (  [uid] int  NOT NULL DEFAULT ((0)),   [rid] int  NOT NULL DEFAULT ((0)), )ALTER TABLE from_users_roles ADD CONSTRAINT from_users_roles_pkey PRIMARY KEY  ([uid], [rid])
['tablehasidentity'] = 1 or 0

Now replace the prefixes in the query 'from_' with 'to_' and the CREATE Statement is finished:

create table [to_users_roles] (  [uid] int  NOT NULL DEFAULT ((0)),   [rid] int  NOT NULL DEFAULT ((0)), )ALTER TABLE to_users_roles ADD CONSTRAINT to_users_roles_pkey PRIMARY KEY  ([uid], [rid]);

Create INSERT Statement

When you want to insert data from one table to another, you have to distinguish between two cases:

TablehasIdentity == 0

INSERT INTO to_users_roles SELECT * FROM from_users_roles

TablehasIdentity == 1

This case is a bit more complex. The statement requires a column list and IDENTITY_INSERT switched on.

DECLARE @Query nvarchar(4000)
DECLARE @columnlist nvarchar(4000)

// Result of this query e.g.: "[cid], [pid], [nid], [uid], [subject]"
SET @columnlist = (SELECT SUBSTRING((SELECT ', ' + QUOTENAME(COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS  WHERE TABLE_NAME = 'from_users_roles' ORDER BY ORDINAL_POSITION FOR XML path('')), 3,  200000))

SET @query ='SET IDENTITY_INSERT to_users_roles ON; INSERT INTO to_users_roles (' + @columnlist + ')  SELECT  ' + @columnlist + ' FROM from_users_roles; SET IDENTITY_INSERT to_users_roles OFF'
exec sp_executesql @query;

This worked out for me pretty well.

like image 53
larrydahooster Avatar answered Oct 26 '22 19:10

larrydahooster


The latest version of Azure SQL DB, now in Preview, supports the SELECT INTO syntax and no longer requires a clustered index. For a detailed description of its features, and how to use it, see http://azure.microsoft.com/en-us/documentation/articles/sql-database-preview-whats-new/

like image 25
Stuart Ozer Avatar answered Oct 26 '22 19:10

Stuart Ozer