How can I copy the structure of a table into a temp table (or table variable) excluding the nullability of each column? Mainly I need to copy the column names and data types, but not nullability, keys, indexes, etc. I'll also note that this must be done programmatically within a procedure, so I can't just generate a create table
script and modify it. The best I've come up with has been:
select top 0 *
into #MyTempTable
from dbo.MyTable
which copies the nullability of each field, thus defeating the purpose for me.
I've also played around with dynamic SQL and extracting the column data from table INFORMATION_SCHEMA.COLUMNS
to build the create table
statement, but the issue there is that the temp table goes out of scope after the dynamic SQL statement executes and control is returned to the "main" procedure. (And I'd rather not jam the rest of the procedure into the dynamic SQL statement.) If there were a way to return the temp table from the exec (@Sql)
statement or keep it in scope somehow, it might work, but I don't know that there's a way to do that.
Related questions:
Best Answer
For table variables there is not much you can do. However, for temporary tables (even local ones -- i.e. those with names starting with a single
#
) there is quite a bit that can be done.With regards to the behavior of local temporary tables not surviving the end of the process in which they were created, the place where people seem to get stuck is in assuming that they can only be created. That might be true for table variables (which is why they won't help here), but not so true for temporary tables (local or global): they can also be altered ! And, because local temporary tables are available to sub-processes, and because any changes made to them in a sub-process survive the ending of that sub-process, they can be created in the "current" scope and then altered in a sub-process. The end result will be the desired structure in the current scope :-) !
So you don't need to approach this problem in terms of needing to create the local temporary table with the perfect structure, just so long as there is a programmatic means of determining what changes should be made. And for this particular request that is (thankfully) not terribly difficult. Once the temporary table is created, we just look at the columns of the source table to get their names, datatypes, and optional collation (the three pieces needed for the
ALTER TABLE
statement). Then we just construct a Dynamic SQL string with theALTER TABLE
statements that adjust the nullability as desired. Execute that and all will be right with the world.Set up the test:
For this test we will use a local temporary table as the table to copy, but that is just to make for an easier test, and a permanent table will behave the same way.
Run the test:
Finding the nullability is rather easy. But you can't issue an
ALTER COLUMN
statement without specifying the datatype. The datatype is provided in proper format by thesys.dm_exec_describe_first_result_set()
DMF, but that was introduced in SQL Server 2012, hence it won't help on SQL Server 2008 R2. So, we have to rebuild the actual datatypes, which means you need to: dividemax_length
by 2 forNCHAR
andNVARCHAR
; usescale
by itself fortime
,datetime2
, anddatetimeoffset
; and use bothscale
andprecision
fordecimal
andnumeric
( <sarcasm> so much fun </sarcasm> ).NOTE: Please remember to remove the two references to
tempdb.
in the code below when using this outside of a testing scenario. Those references -- noted in inline comments in the code -- are only there due to the source table (the table to be copied) being a temporary table and existing intempdb
.Check the results:
The following query will display the columns and their datatypes and nullability. You will see that all fields now have
is_nullable
showing as1
:-).