How to allow temporary tables to accept null values - sql

If you create temp tables using "insert into" in SQL Server it uses the first insert to determine whether a column accepts null value or not. if the first insert has null value the column become nullable otherwise it will be non-nullable.
Is there a way to create temp tables using "insert into" to accept null values?
Example
This works without any problem
Select 'one' as a , null as b
into #temp
insert into #temp
Select 'two' as a , 500 as b
However this throws "Cannot insert the value NULL into column 'b'"
Select 'one' as a , 500 as b
into #temp
insert into #temp
Select 'two' as a , null as b
I know I could do create Table or alter column statement but I want to do it without rewriting hundreds of the existing queries.

How about this?
Select CONVERT(varchar(100), 'one') as a , CONVERT(int, 500) as b
into #temp
insert into #temp
Select 'two' as a , null as b
select * from #temp order by 1

I would workaround this by explicitly creating temporary table before first insert.
create table #temp (a varchar(10) not null, b int null)

(Un)fortunately, this question is too popular and appears at the top for Sybase ASE 15.7 as well, so just adding my answer for Sybase here.
For me neither of cast, convert or coalesce worked, but a case statement did (which is what coalesce is, but eh...)
select
a = case when 1 = 0 then null else 'one' end,
b = case when 1 = 0 null else 500 end
into #temp

This is an old question but I had a similar issue where I UNION NULLs to the initial query which may have helped the OP.
Select 'one' as a , 500 as b
into #temp
UNION
SELECT NULL, NULL
insert into #temp
Select 'two' as a , NULL as b
Putting it here so the next time I need to do this and forget how...

Related

Convert Stored procedure result from NULL to 0

I have temp table accepting result set of executing stored proc. I can't change stored proc. The sp return null columns in some rows but I want to convert NULL to 0 when insert them into the temp table. How to do it easily?
My SQL is like:
Insert into #temp (co1, co2, co3)
exec sp_xxx
co3 from sp_xxx might be NULL, but I want to convert it to 0 and store in #temp.col3
Give it a try,
ISNULL(COLUMN_NAME, 0)
Insert into #temp (co1, co2, co3);
exec sp_xxx;
-- update value where column have null value :
update #temp set col1=isnull(col1,0), col2=isnull(col2,0), col3=isnull(col3,0)
where (col1 is null) or (col2 is null) or (col3 is null)
You can create temp table with 3 more comuputed columns value of which is based on your current columns..
Example below..
CREATE TABLE #Products
(
ProductID int IDENTITY (1,1) NOT NULL
, QtyAvailable smallint
, UnitPrice money
, InventoryValue AS isnull(QtyAvailable,0)
)
insert into #Products(QtyAvailable,UnitPrice)
values (null,10),(20,10)
select * from #Products
In the above example InventoryValue is the computed column and value is populated based on QtyAvailable value..
Hope it helps!
As Vikram says, after retrieving the data into your temp table you can then update the values accordingly. if it is just column3 that could be null then
UPDATE #temp
SET col3 = 0
WHERE col3 IS NULL
will do this just fine.
Otherwise you could just do the ISNULL check when you select back from your temp table and use the information later on
SELECT ISNULL(col3, 0)
FROM #temp

replace NULL with Blank value or Zero in sql server

I have a temp table and in that one of my column total_amount is of integer type and NOT NULL. While querying data, I received NULL values for total_Amount column.
How ever I used following syntax to remove nulls but some how still NULL values appearing, correct me if I am wrong.
Create table #Temp1
(
issue varchar(100) NOT NULL,
total_amount int NOT NULL
)
This is my query
Case when total_amount = 0 then 0
else isnull(total_amount, 0)
end as total_amount
I am facing issue at my else part.
You can use the COALESCE function to automatically return null values as 0. Syntax is as shown below:
SELECT COALESCE(total_amount, 0) from #Temp1
The coalesce() is the best solution when there are multiple columns [and]/[or] values and you want the first one. However, looking at books on-line, the query optimize converts it to a case statement.
MSDN excerpt
The COALESCE expression is a syntactic shortcut for the CASE expression.
That is, the code COALESCE(expression1,...n) is rewritten by the query optimizer as the following CASE expression:
CASE
WHEN (expression1 IS NOT NULL) THEN expression1
WHEN (expression2 IS NOT NULL) THEN expression2
...
ELSE expressionN
END
With that said, why not a simple ISNULL()? Less code = better solution?
Here is a complete code snippet.
-- drop the test table
drop table #temp1
go
-- create test table
create table #temp1
(
issue varchar(100) NOT NULL,
total_amount int NULL
);
go
-- create test data
insert into #temp1 values
('No nulls here', 12),
('I am a null', NULL);
go
-- isnull works fine
select
isnull(total_amount, 0) as total_amount
from #temp1
Last but not least, how are you getting null values into a NOT NULL column?
I had to change the table definition so that I could setup the test case. When I try to alter the table to NOT NULL, it fails since it does a nullability check.
-- this alter fails
alter table #temp1 alter column total_amount int NOT NULL
You should always return the same type on all case condition:
In the first one you have an character and on the else you have an int.
You can use:
Select convert(varchar(11),isnull(totalamount,0))
or if you want with your solution:
Case when total_amount = 0 then '0'
else convert(varchar(11),isnull(total_amount, 0))
end as total_amount
Try This
SELECT Title from #Movies
SELECT CASE WHEN Title = '' THEN 'No Title' ELSE Title END AS Titile from #Movies
OR
SELECT [Id], [CategoryId], ISNULL(nullif(Title,''),'No data') as Title, [Director], [DateReleased] FROM #Movies
Different ways to replace NULL in sql server
Replacing NULL value using:
1. ISNULL() function
2. COALESCE() function
3. CASE Statement
SELECT Name as EmployeeName, ISNULL(Bonus,0) as EmployeeBonus from tblEmployee
SELECT Name as EmployeeName, COALESCE(Bonus, 0) as EmployeeBonus
FROM tblEmployee
SELECT Name as EmployeeName, CASE WHEN Bonus IS NULL THEN 0
ELSE Bonus END as EmployeeBonus
FROM tblEmployee
Replace Null Values as Empty: ISNULL('Value','')
Replace Null Values as 0: ISNULL('Value',0)

SQL Server 2005 - Insert with Select for 1 Value

Basically I have 2 tables but the problem is I would like to insert data from table A column A to table B column C.
But when I try to this I get an error
My subquery is:
SELECT TOP 1 [Id]
From [A]
Where [B] = 'ValueCon'
And here is my insert query
INSERT INTO [B]
([BA]
,[BB]
)
VALUES
('TestData'
,(SELECT TOP 1 [Id]
From [A]
Where [AB] = 'ValueCon')
)
There is no need to worry about data types as they are all matching.
I get the following error:
Subqueries are not allowed in this context. Only scalar expressions are allowed.
I have seen many complex ways of getting around this but just need something simple.
May be if you use a declared param, you can use it to the INSERT
DECLARE #theInsertedId INT;
SELECT TOP 1 #theInsertedId=[Id]
From [A]
Where [B] = 'ValueCon'
INSERT INTO [B]
([BA]
,[BB]
)
VALUES
('TestData'
,#theInsertedId
)
Sorry for by bad english! Hope this help!
Read up on the proper syntax for INSERT! It's all very well documented in the SQL Server Books Online ....
Either you have INSERT and VALUES and you provide atomic values (variables, literal values), e.g.
INSERT INTO [B] ([BA], [BB])
VALUES ('TestData', #SomeVariable)
OR you're using the INSERT ... SELECT approach to select column from another table (and you can also mix in literal values), e.g.
INSERT INTO [B] ([BA], [BB])
SELECT
TOP 1 'TestData', [Id]
FROM [A]
WHERE [AB] = 'ValueCon'
but you cannot mix the two styles. Pick one or the other.
You could just have a single select statement?
Not sure if this will work for what you are trying to do....
declare #a table
(
ab varchar(20),
id varchar(20)
)
insert #a
select 'ValueCon',1
union all
select 'ValueCon',2
union all
select 'Con',100
declare #b table
(
ba varchar(20),
bb varchar(20)
)
insert #b (ba,bb)
select top 1 'TestData',id from #a where ab='Valuecon'
select * from #a
select * from #b

INSERT INTO With a SubQuery and some operations

I'm trying to insert some data to a table contains two things : "a string" and "maximum number in Order column + 1".
This is my query:
INSERT INTO MyTable ([Text],[Order])
SELECT 'MyText' , (Max([Order]) + 1)
FROM MyTable
What is going wrong with my query?
I'm using Microsoft SQL Server 2005 SP3.
You can test this query like this:
I don't receive error:
create table #MyTable
(
[Text] varchar(40),
[Order] int NOT NULL
)
INSERT INTO #MyTable([Text],[Order])
SELECT 'MyText' [Text], isnull(max([order]) + 1, 0) [Order]
FROM #MyTable
drop table #MyTable
Original:
INSERT INTO MyTable ([Text],[Order])
SELECT 'MyText' [Text], max([Order]) + 1 [Order]
FROM MyTable
or
INSERT INTO MyTable ([Text],[Order])
SELECT top 1 'MyText' [Text], max([Order]) + 1 [Order]
FROM MyTable
limit is not valid in SQL Server as far as I know.
Cannot insert the value NULL into column 'Order', table 'master.dbo.MyTable'; column does not allow nulls. INSERT fails. The statement has been terminated.
This means that the Order column isn't allowed to be null, and that the Max([Order]) + 1 part of your column returns NULL.
This is because your table is empty, as you already noticed by yourself.
You can work around this by replacing NULL by a real number in the query, using ISNULL():
INSERT INTO MyTable ([Text],[Order])
SELECT 'MyText' , (isnull(Max([Order]),0) + 1)
FROM MyTable
Unless he has a column named OrderBy
then he would have to add / assign all values within that Insert especially if the column does not allow for nulls
sounds like fully qualifying the Insert with the dbo.MyTable.Field may make more sense.
also why are you naming fields with SQL Key words...???
INSERT INTO MyTable ([Text],[Order] Values('MyTextTest',1)
try a test insert first..

Select records with order of IN clause

I have
SELECT * FROM Table1 WHERE Col1 IN(4,2,6)
I want to select and return the records with the specified order which i indicate in the IN clause
(first display record with Col1=4, Col1=2, ...)
I can use
SELECT * FROM Table1 WHERE Col1 = 4
UNION ALL
SELECT * FROM Table1 WHERE Col1 = 6 , .....
but I don't want to use that, cause I want to use it as a stored procedure and not auto generated.
I know it's a bit late but the best way would be
SELECT *
FROM Table1
WHERE Col1 IN( 4, 2, 6 )
ORDER BY CHARINDEX(CAST(Col1 AS VARCHAR), '4,2,67')
Or
SELECT CHARINDEX(CAST(Col1 AS VARCHAR), '4,2,67')s_order,
*
FROM Table1
WHERE Col1 IN( 4, 2, 6 )
ORDER BY s_order
You have a couple of options. Simplest may be to put the IN parameters (they are parameters, right) in a separate table in the order you receive them, and ORDER BY that table.
The solution is along this line:
SELECT * FROM Table1
WHERE Col1 IN(4,2,6)
ORDER BY
CASE Col1
WHEN 4 THEN 1
WHEN 2 THEN 2
WHEN 6 THEN 3
END
select top 0 0 'in', 0 'order' into #i
insert into #i values(4,1)
insert into #i values(2,2)
insert into #i values(6,3)
select t.* from Table1 t inner join #i i on t.[in]=t.[col1] order by i.[order]
Replace the IN values with a table, including a column for sort order to used in the query (and be sure to expose the sort order to the calling application):
WITH OtherTable (Col1, sort_seq)
AS
(
SELECT Col1, sort_seq
FROM (
VALUES (4, 1),
(2, 2),
(6, 3)
) AS OtherTable (Col1, sort_seq)
)
SELECT T1.Col1, O1.sort_seq
FROM Table1 AS T1
INNER JOIN OtherTable AS O1
ON T1.Col1 = O1.Col1
ORDER
BY sort_seq;
In your stored proc, rather than a CTE, split the values into table (a scratch base table, temp table, function that returns a table, etc) with the sort column populated as appropriate.
I have found another solution. It's similar to the answer from onedaywhen, but it's a little shorter.
SELECT sort.n, Table1.Col1
FROM (VALUES (4), (2), (6)) AS sort(n)
JOIN Table1
ON Table1.Col1 = sort.n
I am thinking about this problem two different ways because I can't decide if this is a programming problem or a data architecture problem. Check out the code below incorporating "famous" TV animals. Let's say that we are tracking dolphins, horses, bears, dogs and orangutans. We want to return only the horses, bears, and dogs in our query and we want bears to sort ahead of horses to sort ahead of dogs. I have a personal preference to look at this as an architecture problem, but can wrap my head around looking at it as a programming problem. Let me know if you have questions.
CREATE TABLE #AnimalType (
AnimalTypeId INT NOT NULL PRIMARY KEY
, AnimalType VARCHAR(50) NOT NULL
, SortOrder INT NOT NULL)
INSERT INTO #AnimalType VALUES (1,'Dolphin',5)
INSERT INTO #AnimalType VALUES (2,'Horse',2)
INSERT INTO #AnimalType VALUES (3,'Bear',1)
INSERT INTO #AnimalType VALUES (4,'Dog',4)
INSERT INTO #AnimalType VALUES (5,'Orangutan',3)
CREATE TABLE #Actor (
ActorId INT NOT NULL PRIMARY KEY
, ActorName VARCHAR(50) NOT NULL
, AnimalTypeId INT NOT NULL)
INSERT INTO #Actor VALUES (1,'Benji',4)
INSERT INTO #Actor VALUES (2,'Lassie',4)
INSERT INTO #Actor VALUES (3,'Rin Tin Tin',4)
INSERT INTO #Actor VALUES (4,'Gentle Ben',3)
INSERT INTO #Actor VALUES (5,'Trigger',2)
INSERT INTO #Actor VALUES (6,'Flipper',1)
INSERT INTO #Actor VALUES (7,'CJ',5)
INSERT INTO #Actor VALUES (8,'Mr. Ed',2)
INSERT INTO #Actor VALUES (9,'Tiger',4)
/* If you believe this is a programming problem then this code works */
SELECT *
FROM #Actor a
WHERE a.AnimalTypeId IN (2,3,4)
ORDER BY case when a.AnimalTypeId = 3 then 1
when a.AnimalTypeId = 2 then 2
when a.AnimalTypeId = 4 then 3 end
/* If you believe that this is a data architecture problem then this code works */
SELECT *
FROM #Actor a
JOIN #AnimalType at ON a.AnimalTypeId = at.AnimalTypeId
WHERE a.AnimalTypeId IN (2,3,4)
ORDER BY at.SortOrder
DROP TABLE #Actor
DROP TABLE #AnimalType
ORDER BY CHARINDEX(','+convert(varchar,status)+',' ,
',rejected,active,submitted,approved,')
Just put a comma before and after a string in which you are finding the substring index or you can say that second parameter.
And first parameter of CHARINDEX is also surrounded by , (comma).