When I create a temp table using a select into in SQL Server, is there a way to specify that a column should be nullable? I have a multi-step process where I'm making a temp table by selecting a lot of columns (which is why I'm not doing a create table #tmp (...)). After I make that temp table, I'm updating some columns and some of those updates might null out a field.
I know I could do an alter table alter column statement to achieve what I want, but I'm curious about whether there's a way to specify this in the select itself. I know you can inline cast your columns to get the desired datatype, but I can't see how you specify nullability.
Nullability is inherited from the source column.
You can lose or gain nullability with an expression:
Example (constant literals appear to be problematic - need a good NOOP function which can return NULL):
CREATE TABLE SO5465245_IN
(
a INT NOT NULL
,b INT NULL
) ;
GO
SELECT COALESCE(a, NULL) AS a
,ISNULL(b, 0) AS b
,COALESCE(10, NULL) AS c1
,COALESCE(ABS(10), NULL) AS c2
,CASE WHEN COALESCE(10, NULL) IS NOT NULL THEN COALESCE(10, NULL) ELSE NULL END AS c3
INTO SO5465245_OUT
FROM SO5465245_IN ;
GO
SELECT TABLE_NAME
,COLUMN_NAME
,IS_NULLABLE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE 'SO5465245%'
ORDER BY TABLE_NAME
,ORDINAL_POSITION ;
GO
DROP TABLE SO5465245_IN ;
GO
DROP TABLE SO5465245_OUT ;
GO
This soulution I've recently come up with and though I should share:
select top 0
B.*
into
TargetTable
from
SourceTable as A
left join SourceTable as B on 1 = 0
This effectively creates a duplicated structure of SourceTable in TargetTable with all columns nullable (at least in sql2008).
CONVERT will make your columns nullable, and works for literals/constants too. Tested in SQL Server 2005/2008.
SELECT
SomeText = CONVERT(varchar(10), 'literal'),
SomeNumber = CONVERT(int, 0)
INTO SO5465245
INSERT SO5465245 VALUES (null, null)
SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, IS_NULLABLE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'SO5465245'
ORDER BY TABLE_NAME, ORDINAL_POSITION
DROP TABLE SO5465245
If you want to inherit nullablity for the destination column irrespective of the source table columns you can follow this query.
SELECT COLUMN1, COLUMN2, COLUMN3 INTO DestinationTable from SourceTable
if this was your query where COLUMN1,COLUMN2,COLUMN3 were not nullable in SourceTable then change the query as
SELECT NULL COLUMN1, NULL COLUMN2, NULL COLUMN3 INTO DestinationTable from SourceTable
so, this will allow you to insert null values in to the Destination table.
I recently had the same issue - I wanted to use "select into", wanted all columns in the target table to be nullable & a repeatable approach where I didn't have to know the names of the fields in the source table.
select *
into dbo.I_Data
from
(select 1[Z_1]) A
full join (select null[Z_2], * from dbo.S_Data) B on A.Z_1 = B.Z_2
where
dbo.S_Data is the source data table and
[Z_1] & [Z_2] are two dummy columns used for the join
Then to clean up:
(a) Remove the row of nulls
delete dbo.I_Data where [Z_1] = 1
(b) Remove the dummy fields:
alter table dbo.I_Data
drop column [Z_1], [Z_2]
Regards.
Related
This question already has answers here:
How to create table using select query in SQL Server?
(4 answers)
Closed 9 years ago.
I want to create a table from select query result in SQL Server, I tried
create table temp AS select.....
but I got an error
Incorrect syntax near the keyword 'AS'
Use following syntax to create new table from old table in SQL server 2008
Select * into new_table from old_table
use SELECT...INTO
The SELECT INTO statement creates a new table and populates it with
the result set of the SELECT statement. SELECT INTO can be used to
combine data from several tables or views into one table. It can also
be used to create a new table that contains data selected from a
linked server.
Example,
SELECT col1, col2 INTO #a -- <<== creates temporary table
FROM tablename
Inserting Rows by Using SELECT INTO
Standard Syntax,
SELECT col1, ....., col# -- <<== select as many columns as you want
INTO [New tableName]
FROM [Source Table Name]
Please be careful,
MSSQL: "SELECT * INTO NewTable FROM OldTable"
is not always the same as
MYSQL: "create table temp AS select.."
I think that there are occasions when this (in MSSQL)
does not guarantee that all the fields in the new table are of the same type as the old.
For example :
create table oldTable (field1 varchar(10), field2 integer, field3 float)
insert into oldTable (field1,field2,field3) values ('1', 1, 1)
select top 1 * into newTable from oldTable
does not always yield:
create table newTable (field1 varchar(10), field2 integer, field3 float)
but may be:
create table newTable (field1 varchar(10), field2 integer, field3 integer)
Please try:
SELECT * INTO NewTable FROM OldTable
Try using SELECT INTO....
SELECT ....
INTO TABLE_NAME(table you want to create)
FROM source_table
Select [Column Name] into [New Table] from [Source Table]
I have a table of more than 2 million rows and over 100 columns. I need to run a query that checks if there are any null values in any row or column of the table and return an ID number where there is a null. I've thought about doing the following, but I was wondering if there is a more concise way of checking this?
SELECT [ID]
from [TABLE_NAME]
where
[COLUMN_1] is null
or [COLUMN_2] is null
or [COLUMN_3] is null or etc.
Your method is fine. If your challenge is writing out the where statement, then you can run a query like this:
select column_name+' is null or '
from information_schema.columns c
where c.table_name = 'table_name'
Then copy the results into a query window and use them for building the query.
I used SQL Server syntax for the query, because it looks like you are using SQL Server. Most databases support the INFORMATION_SCHEMA tables, but the syntax for string concatenation varies among databases. Remember to remove the final or at the end of the last comparison.
You can also copy the column list into Excel and use Excel formulas to create the list.
You can use something similar to the following:
declare #T table
(
ID int,
Name varchar(10),
Age int,
City varchar(10),
Zip varchar(10)
)
insert into #T values
(1, 'Alex', 32, 'Miami', NULL),
(2, NULL, 24, NULL, NULL)
;with xmlnamespaces('http://www.w3.org/2001/XMLSchema-instance' as ns)
select ID,
(
select *
from #T as T2
where T1.ID = T2.ID
for xml path('row'), elements xsinil, type
).value('count(/row/*[#ns:nil = "true"])', 'int') as NullCount
from #T as T1
I want to crate a temp table from select query (My table has many columns, therefore I don't want to create the temp table manually)
I use the following query:
SELECT * INTO #TempTable
FROM MyTable
WHERE ...
If this query return empty rows, it won't create #TempTable. Hence, I cannot use this #TempTable for the next queries.
Is there a way to resolve this?
If the query SELECT * FROM MyTable WHERE ... in your code you posted:
SELECT *
INTO TempTable
FROM MyTable WHERE ...
returned no rows, it will create an empty TempTable, but it won't fill any data in it if there is no rows matched the WHERE clause. But it should create the table TempTable at least with the same structure as the MyTable and it will be empty.
For example this:
SELECT * INTO TempTable FROM MyTable WHERE 1 <> 1;
Will always create an empty table TempTable with the same structure as MyTable since the predicate 1 <> 1 is always false.
However you can declare it like so:
DECLARE #Temp TABLE(Field1 int, ...);
This is because you are dynamically creating and populating temporary table and not creating it explicitly.In such scenario, you must check the existence of the temp table in the beginning before you create one.
Try this:
IF OBJECT_ID('tempdb..#TempTable') IS NOT NULL
BEGIN
DROP TABLE #TempTable
END
SELECT * INTO #TempTable FROM MyTable
Select * From #TempTable
your query
SELECT * INTO #TempTable
FROM MyTable
WHERE ...
will create an empty table if the select returns no rows
here my query-
SELECT final.* into #FinalTemp from
(
select * from #temp1
UNION
select * from #temp2
UNION
select * from #temp3
UNION
select * from #temp4
)final
but at a time only one temp table exists so how to check if #temp exists then do union or ignore?
You can't have a union or query on a non-existent object at compile time (compiling to a query plan just before execution).
So there is no way to refer to a non-existent table in the same batch
The pattern you have to use is like this: dynamic SQL is a separate batch
IF OBJECT('tempdb..#temp1') IS NOT NULL
EXEC ('SELECT * FROM #temp1')
ELSE IF OBJECT('tempdb..#temp3') IS NOT NULL
EXEC ('SELECT * FROM #temp3')
ELSE IF OBJECT('tempdb..#temp3') IS NOT NULL
EXEC ('SELECT * FROM #temp3')
...
Would you not be better creating #FinalTemp as an explicit temp table at the top of your query, and then replace your existing population methods which I assume look like this:
SELECT * INTO #temp1 FROM ... /* Rest of Query */
With:
INSERT INTO #FinalTemp (Columns...)
SELECT * FROM ... /* Rest of Query */
And then you don't have to do this final union step at all. Or, if you do need 4 separate temp tables (perhaps for multi-step operations on each), define each of them at the start of your query, and then they will all exist when you perform the union.
Now, given you've said only one will be populated (so the others will be empty), it's probably moot, but I always tend to use UNION ALL to combine disjoint tables - unless you're implicitly relying on UNIONs duplicate removal feature?
You can declare Temp Tables using the same syntax as you do for real tables:
CREATE TABLE #FinalTemp (
ColumnA int not null primary key,
ColumnB varchar(20) not null,
ColumnC decimal(19,5) null,
)
Or, as you've also alluded to, you can use table variables rather than temp tables:
declare #FinalTemp table (
ColumnA int not null primary key,
ColumnB varchar(20) not null,
ColumnC decimal(19,5) null,
)
The predominant different (so far as I'm concerned) is that table variables follow the same scoping rules as other variables - they're not available inside a called stored procedure, and they're cleaned up between batches.
I am trying to select some fields from one table and insert them into an existing table from a stored procedure. Here is what I am trying:
SELECT col1, col2
INTO dbo.TableTwo
FROM dbo.TableOne
WHERE col3 LIKE #search_key
I think SELECT ... INTO ... is for temporary tables which is why I get an error that dbo.TableTwo already exists.
How can I insert multiple rows from dbo.TableOne into dbo.TableTwo?
SELECT ... INTO ... only works if the table specified in the INTO clause does not exist - otherwise, you have to use:
INSERT INTO dbo.TABLETWO
SELECT col1, col2
FROM dbo.TABLEONE
WHERE col3 LIKE #search_key
This assumes there's only two columns in dbo.TABLETWO - you need to specify the columns otherwise:
INSERT INTO dbo.TABLETWO
(col1, col2)
SELECT col1, col2
FROM dbo.TABLEONE
WHERE col3 LIKE #search_key
There are two different ways to implement inserting data from one table to another table.
For Existing Table - INSERT INTO SELECT
This method is used when the table is already created in the database earlier and the data is to be inserted into this table from another table. If columns listed in insert clause and select clause are same, they are not required to list them. It is good practice to always list them for readability and scalability purpose.
----Create testable
CREATE TABLE TestTable (FirstName VARCHAR(100), LastName VARCHAR(100))
----INSERT INTO TestTable using SELECT
INSERT INTO TestTable (FirstName, LastName)
SELECT FirstName, LastName
FROM Person.Contact
WHERE EmailPromotion = 2
----Verify that Data in TestTable
SELECT FirstName, LastName
FROM TestTable
----Clean Up Database
DROP TABLE TestTable
For Non-Existing Table - SELECT INTO
This method is used when the table is not created earlier and needs to be created when data from one table is to be inserted into the newly created table from another table. The new table is created with the same data types as selected columns.
----Create a new table and insert into table using SELECT INSERT
SELECT FirstName, LastName
INTO TestTable
FROM Person.Contact
WHERE EmailPromotion = 2
----Verify that Data in TestTable
SELECT FirstName, LastName
FROM TestTable
----Clean Up Database
DROP TABLE TestTable
Ref 1 2
It would work as given below :
insert into Gengl_Del Select Tdate,DocNo,Book,GlCode,OpGlcode,Amt,Narration
from Gengl where BOOK='" & lblBook.Caption & "' AND DocNO=" & txtVno.Text & ""
If the destination table does exist but you don't want to specify column names:
DECLARE #COLUMN_LIST NVARCHAR(MAX);
DECLARE #SQL_INSERT NVARCHAR(MAX);
SET #COLUMN_LIST = (SELECT DISTINCT
SUBSTRING(
(
SELECT ', table1.' + SYSCOL1.name AS [text()]
FROM sys.columns SYSCOL1
WHERE SYSCOL1.object_id = SYSCOL2.object_id and SYSCOL1.is_identity <> 1
ORDER BY SYSCOL1.object_id
FOR XML PATH ('')
), 2, 1000)
FROM
sys.columns SYSCOL2
WHERE
SYSCOL2.object_id = object_id('dbo.TableOne') )
SET #SQL_INSERT = 'INSERT INTO dbo.TableTwo SELECT ' + #COLUMN_LIST + ' FROM dbo.TableOne table1 WHERE col3 LIKE ' + #search_key
EXEC sp_executesql #SQL_INSERT
select *
into existing table database..existingtable
from database..othertables....
If you have used select * into tablename from other tablenames already, next time, to append, you say select * into existing table tablename from other tablenames
IF you want a identity column in new table created with select into then it can be done as below.
SELECT
ID = IDENTITY(INT, 1, 1),
name
INTO table2
FROM table1
If you want to insert into Table_A, from Table_B, only if the column is not in Table_A, then use the following:
BEGIN TRANSACTION
INSERT INTO dbo.Table_A (Column_1)
SELECT DISTINCT Some_Column AS Column_1
FROM dbo.Table_B
WHERE Some_Column
NOT IN (SELECT DISTINCT GroupId
FROM dbo.Table_A)
COMMIT