How to insert value in SQL table if not exists - sql

I'm new in SQL. I'm trying to insert data into a SQL table. If I insert for the first time it works but if I try to do a new insert I get the error
Violation of UNIQUE KEY constraint.
The unique key constraint is on (uc, start_date). The error occurs because there is already the record (-1, 1900-01-01) in the table. Here is my code:
insert into tableA ([start_date],[end_date],[uc],[desc],[ind_sus])
select '1900-01-01' [start_date]
,'9999-12-31'[end_date]
,case when right([DIM], 1) = '|' then '-1'
else right([DIM], 2)
end [uc]
,'' [desc]
,0 [ind_sus]
from tableB b
where right([DIM], 2) NOT IN (select uc from tableA a
where a.uc = right([DIM], 2)
and convert(date,b.[DATETRIAL]) between a.start_date and a.end_date)
group by case when right([DIM], 1) = '|' then '-1'
else right([DIM], 2)
end
The data that I'm trying to insert fulfills the when condition of the case and therefore another (-1, 1900-01-01) as key. I tried:
case when not exists(select uc from tableA where uc = '-1') then '-1'
to insert only if the data doesn't exist. It didn't work because I have to put the same code in the group by clause and I realized that I cannot do a subquery in the group by clause. So, is there a way to check at the case clause level if a value already exist before inserting? Or should I rewrite the request in another way? Database can't be modified
I need suggestions please.

In order to be able to check and insert data when not exists you need to use MERGE operator (see docs for more info).
Since you did not provide us with test data, I'm not sure I can easily update your query, so here is an example I made up to show you how to do things you need using MERGE.
Create table and insert 1 row with id = 1:
create table some_table(id int primary key, text_col varchar(10));
insert into some_table values(1, 'first');
Try to insert a line with same id
insert into some_table values(1, 'another first'); -- it fails of course
same thing using merge
merge into some_table -- target table
using
(select 1 id, 'another first' text_col) new_data -- source data
on some_table.id = new_data.id -- column to check on
when not matched then
insert (id, text_col) values(new_data.id, new_data.text_col);
I hope this helps
My try to change your query to merge would be like that
(keep in mind I did not tested it so fixing syntax or possible data errors is up to you)
merge into tableA a
using (select uc
,'1900-01-01' [start_date]
,'9999-12-31'[end_date]
,case when right([DIM], 1) = '|' then '-1'
else right([DIM], 2) end [uc]
,'' [desc]
,0 [ind_sus]
from tableB b
group by case when right([DIM], 1) = '|' then '-1'
else right([DIM], 2)
end) b
on a.right([DIM], 2) = b.uc
and convert(date,b.[DATETRIAL]) between a.start_date and a.end_date
when not matched then
insert([start_date],[end_date],[uc],[desc],[ind_sus])
values(b.start_date, b.end_date, b.uc, b.desc, b.ind_sus)

Related

Order By TableName and columnname

Lets say I have a table with following columns:
Id,TableName,Columnname
Normally If I would like to do a select with ordering on TableName Primary and ColumnName secondary I would do
Select * From MyTable Order By TableName,ColumnName
Now say I would like a special case of ordering depending on TableName
Select * From MyTable Order By Case
When TableName = 'Foo' Then '1'
When TableName = 'Bar' Then '2'
When TableName = 'Test' Then '3'
ELSE 1000 END;
How do I combine the second alternative with the first alternative, that is special ordering on first TableName and then order the Columnnames with that TableName?
I'm running Microsoft SQL
Thanks in advance.
Just add column in order list, like any other ORDER BY :)
Select * From MyTable Order By Case
When TableName = 'Foo' Then '1'
When TableName = 'Bar' Then '2'
When TableName = 'Test' Then '3'
ELSE 1000 END, ColumnName;
The case method is fine. I would often use this short-cut:
Select *
From MyTable
Order By charindex(TableName, ',Test,Bar,Foo,') desc
This is a wee bit arcane. charindex() returns the position of the name in the string. So, this form will not work for all string values, but it can be generalized:
Order By charindex(',' + TableName + ',', ',Test,Bar,Foo,') desc
The reversal of the list is to handle missing values. These are assigned a value of 0, so by putting the values in reverse order, the missing ones come last. Note that if I know all the values, then I would write this as:
Order By charindex(TableName, ',Foo,Bar,Test,') asc
As alternative, you could
1) create a new table
CREATE TABLE_ORDER (TABLE_NAME VARCHAR(100) NOT NULL, ORDER_VAL INT);
ALTER TABLE TABLE_ORDER ADD CONSTRAINT TABLE_ORDER_PK PRIMARY KEY(TABLE_NAME);
2) insert into it appropriate values:
INSERT INTO TABLE_ORDER (TABLE_NAME, ORDER_VAL) VALUES ('Foo', 1);
INSERT INTO TABLE_ORDER (TABLE_NAME, ORDER_VAL) VALUES ('Bar', 2);
INSERT INTO TABLE_ORDER (TABLE_NAME, ORDER_VAL) VALUES ('Test', 3);
3) Use the following query
SELECT A.*
FROM MYTABLE A
LEFT JOIN TABLE_ORDER B ON A.TABLENAME= B.TABLE_NAME
ORDER BY B.ORDER_VAL, A.COLUMNNAME

How to allow temporary tables to accept null values

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...

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..

sql query serial number

I have written a stored procedure in SQL Server 2000. I want a serial number for output table.
So when I run this stored proc I get this error:
An explicit value for the identity column in table
'#tmpSearchResults1' can only be specified when a column list is used
and IDENTITY_INSERT is ON.
I have tried with set IDENTITY_INSERT #tmpSearchResults1 on
Create Procedure dbo.usp_mobile_All_KeyWord(#searchkey varchar(30))
AS
CREATE TABLE #tmpSearchResults
(
property_id varchar(255),
property_number varchar(255),
auction_date_reason varchar(255)
)
INSERT INTO #tmpSearchResults
SELECT
p.property_id, p.property_number, p.auction_date_reason
FROM
Pr p
INNER JOIN
Au a ON p.auction_id = a.auction_id
INNER JOIN
PrAdd pa ON p.property_id = pa.property_id
INNER JOIN state AS s ON s.state_id=pa.state
where
(
(p.archive = 'N'
AND
a.show_on_site = 'Y'
AND
(
(
((p.auction_date >= CONVERT(datetime, CONVERT(varchar, GETDATE(), 103), 103) and (p.auction_date_reason is null or p.auction_date_reason = ''))
or
(p.auction_date <= CONVERT(datetime, CONVERT(varchar, GETDATE(), 103), 103) and ( p.auction_date_reason = 'Accepting Offers' )))
and
pa.property_address_type_id = 1 )) )
and
(state_abbreviation=#searchkey or s.state_name like '%'+''+ #searchkey +''+'%' or city like '%'+''+ #searchkey +''+'%' or pa.address1 like '%'+''+ #searchkey +''+'%'
or pa.address2 like '%'+''+ #searchkey +''+'%')
)
)
CREATE TABLE #tmpSearchResults1
(
i1 int identity,
property_id varchar(255),
property_number varchar(255),
auction_date_reason varchar(255)
)
insert into #tmpSearchResults1
select
property_id ,
property_number,
auction_date_reason
from #tmpSearchResults
order by
case when charindex(#searchkey,state) >0 then 1000 else 0 end desc,
case when charindex(#searchkey,statename) >0 then 1000 else 0 end desc,
case when charindex(#searchkey,city) >0 then 1000 else 0 end desc,
case when charindex(#searchkey,address2) >0 then 1000 else 0 end desc,
case when charindex(#searchkey,address1) >0 then 1000 else 0 end desc,
case when charindex(#searchkey,short_description) >0 then 1000 else 0 end desc
select * from #tmpSearchResults1
Plz do help me
The error code is very very very clear.
The relevant portion is ...when a column list is used....
You need to specify your column list in the INSERT statement.
INSERT INTO #tmpSearchResults
(i1,
property_id,
property_number,
auction_date_reason)
SELECT
p.property_id, p.property_number, p.auction_date_reason
FROM...
First, there is a comma too much in the SELECT part of your second statement:
insert into #tmpSearchResults1
select
property_id ,
property_number,
auction_date_reason , <-- THIS ONE!!
from #tmpSearchResults
The last column of a SELECT statement must be without a comma.
So this would be correct:
insert into #tmpSearchResults1
select
property_id ,
property_number,
auction_date_reason
from #tmpSearchResults
Second, did you read this part of the error message?
An explicit value [...] can only be specified when a column list is used
The "column list" part means that you have to specify the columns in the INSERT part:
insert into #tmpSearchResults1
(property_id, property_number, auction_date_reason)
select
property_id ,
property_number,
auction_date_reason
from #tmpSearchResults
You can get away with not specifying the columns when the number of columns in the SELECT statement is the same as in the table in which they should be inserted (and if the data types match).
If one of these conditions is not met, you need to specify the columns because otherwise SQL Server doesn't know which value to insert into which column.

simple insert procedure, check for duplicate

I am creating a program that is going to insert data into a table which is pretty simple
But my issue is I want my insert statement to make sure that it isnt inserting duplicate data
I want to somehow check the table the data is going into to make sure that there isnt a row with the same indivualid and categoryid and value
So if I am inserting
indivualid = 1
categorid = 1
value = 1
and in my table there is a row with
indivualid = 1
categorid = 1
value = 2
my data would still be inserted
but if there was a row with
indivualid = 1
categorid = 1
value = 1
then it wouldnt
I tried this
IF #value = 'Y'
OR #value = 'A'
OR #value = 'P'
AND NOT EXISTS
(SELECT categoryid,
individualid
FROM ualhistory
WHERE categoryid = #cat
AND individualid = #id)
INSERT INTO individuory(categoryid, individualid, value, ts)
VALUES (#cat,
#id,
#yesorno,
getdate())
but it still inserts duplicates.
You can do that in the following manner:
insert into
individuory(categoryid, individualid, value, ts)
VALUES (#cat, #id, #yesorno, getdate())
where not exists
(select 1 from individuory where categoryid=#cat and individualid=#id)
Now, the exact problem with your approach is that you are not associating the ORs and therefore, the condition becomes true and always inserts the data. You can change your statement to this:
if ((#value = 'Y' or #value = 'A' or #value = 'P')
and not EXISTS
(SELECT categoryid, individualid FROM ualhistory WHERE categoryid = #cat
and individualid = #id) )
INSERT INTO individuory(categoryid, individualid, value, ts)
VALUES (#cat, #id, #yesorno, getdate())
And I think it will work also.
ALTER TABLE individuory
ADD CONSTRAINT myConstarint
UNIQUE (categoryid, individualid, value)
Add a UNIQUE constraint on (individualid, categoryid, value) and the server won't let you insert a duplicate row.
http://msdn.microsoft.com/en-us/library/ms189862.aspx