INSERT IF NOT EXISTS with NULL value - sql

I have two tables: tags and linking table photos_tags. I want to add a new tag, so I check if the tag is already in the tags table and if not I insert one. My tables look something like this: tags(id, name), photos_tags(photos_id, tags_id). Now I tried to do this with:
IF NOT EXISTS (SELECT * FROM tags WHERE name=*tagsName*)
INSERT INTO tags VALUES (NULL, *tagsName*); --NULL used for autonumbering
I've also tried:
INSERT INTO tags (
SELECT NULL, *tagsName*
WHERE NOT EXISTS (
SELECT * FROM tags
WHERE name=*tagsName*
)
);
Both statements result in syntax errors:
in the first statement near if
in the second statement near select
What should my query look like?

Create a UNIQUE constraint on tags.name and use this:
INSERT OR IGNORE
INTO tags (id, name)
VALUES (NULL, 'tagsName')
If for some reason you can't or don't want to do this, use this:
INSERT
INTO tags (id, name)
SELECT NULL, 'tagsName'
WHERE NOT EXISTS
(
SELECT NULL
FROM tags
WHERE name = 'tagsName'
)

INSERT INTO tags (name)
SELECT 'tagsName'
WHERE NOT EXISTS (SELECT 1 FROM tags WHERE name = 'tagsName');
OR
INSERT OR IGNORE
INTO tags (id, name)
VALUES (NULL, 'tagsName')
if you have a unique constraint

Related

Insert into table from select only when select returns valid rows

I want to insert into table from select statement but it is required that insert only happens when select returns valid rows. If no rows return from select, then no insertion happens.
insert into products (name, type) select 'product_name', type from prototype where id = 1
However, the above sql does insertion even when select returns no rows.
It tries to insert NULL values.
I know the following sql can check if row exists
select exists (select true from prototype where id = 1)
How to write a single SQL to add the above condition to insert to exclude the case ?
You are inserting the wrong way. See the example below, that doesn't insert any row since none matches id = 1:
create table products (
name varchar(10),
type varchar(10)
);
create table prototype (
id int,
name varchar(10),
type varchar(10)
);
insert into prototype (id, name, type) values (5, 'product5', 'type5');
insert into prototype (id, name, type) values (7, 'product7', 'type7');
insert into products (name, type) select name, type from prototype where id = 1
-- no rows were inserted.

Referencing inserted ID in multiple insert transactions in Postgres

I need to build a SQL query that must be able to insert data in a first table, grab the inserted ID and then use it as foreign key in the following tables.
WITH inserted AS (
INSERT INTO firstTable (name) VALUES ('somename') RETURNING id
)
SELECT * FROM inserted; -- this has the inserted id
INSERT INTO secondTable (name, foreign_id) VALUES ('someexternalname', ???)
So how do I reference the id in inserted in the secondTable insert?
You have completed this 80% percent, the complete SQL is:
with inserted as (
insert into first_table(name) values ('somename') returning id
)
insert into second_table(name, foreign_id) select 'someexternalname',id from inserted
You can do this:
WITH inserted AS (
INSERT INTO firstTable (name) VALUES ('somename') RETURNING id
)
INSERT INTO secondTable (name, foreign_id)
SELECT
'someexternalname',
id
FROM inserted;
You can try this:
INSERT INTO secondTable (name, foreign_id) VALUES ('someexternalname', (SELECT
MAX (id) FROM firstTable))

How to insert conditionally in Oracle?

I've read here that the syntax looks like this:
INSERT
WHEN ([Condition]) THEN
INTO [TableName] ([ColumnName])
VALUES ([VALUES])
ELSE
INTO [TableName] ([ColumnName])
VALUES ([VALUES])
SELECT [ColumnName] FROM [TableName];
But I don't want to provide values from another table. I just want to type them, so I've got:
INSERT
WHEN EXISTS (SELECT 1 FROM FOO WHERE NAME = 'JOE')
THEN
INTO BAR (NAME, AGE)
VALUES ('JOE', 50)
and this produces exception: ORA-00928: missing SELECT keyword.
I want to perform an insert if given value is found in another table.
Using with select works. Your query wasn't working because there is a problem with values keyword when inserting conditionally.
INSERT
WHEN EXISTS (SELECT 1 FROM FOO WHERE NAME = 'JOE')
THEN
INTO BAR (NAME, AGE)
SELECT 'JOE', 50 FROM DUAL
So, I've found an indirect way here and solution for my question would be:
INSERT INTO BAR (NAME, AGE)
SELECT 'JOE', 50
FROM DUAL
WHERE EXISTS (SELECT 1 FROM FOO WHERE NAME = 'JOE')
but it doesn't explain why I have to use SELECT statement in INSERT WHEN

Sql insert multiple rows if not exists

I have a sql table that has two columns id and name. I have list of names about 20 and I need to write a query that checks if name exists before insert.
Is there a better way of doing this rather then just having the below query 20 times but with different names (I need do this in t-sql):
IF NOT EXISTS(SELECT*
FROM mytable
WHERE name = 'Dan')
BEGIN
INSERT INTO mytable
(name)
VALUES ('dan')
END
INSERT INTO MyTable (Name)
SELECT NewNames.Name
FROM ( VALUES ('Name1'), ('Name2'), ('Name3') ) AS NewNames (Name)
WHERE NOT EXISTS ( SELECT 1
FROM MyTable AS MT
WHERE MT.Name = NewNames.Name );
I think you could use a merge statement:
MERGE INTO myTable AS Target
USING (VALUES ('name1'),('name2'),('...')) AS source (NAME)
ON Target.NAME = Source.NAME
WHEN NOT MATCHED BY TARGET THEN
INSERT (NAME) VALUES (name)
You can filter values with NOT EXISTS
INSERT INTO myTable (
Name
)
SELECT DISTINCT
Name
FROM (
VALUES ('Name 1'),
('Name 2')
) AS NewNames(Name)
WHERE
NOT EXISTS (SELECT 1 FROM TargetTable WHERE myTable.Name = NewNames.Name)
If your new names are in another table, you can change the select query in the above one.
Please note, that the DISTINCT keyword is necessary to filter out the duplications in the source data.
I would do this using insert:
with names as (
select 'Dan' as name union all
select 'name2' union all
. . .
)
insert into myTable(name)
select distinct name
from myTable
where not exists (select 1 from mytable t2 where t2.name = t.name);
Note: you may want to create a unique index on mytable(name) so the database does the checking for duplicates.
untested so there might be some minor errors:
merge into mytable x
using (
values ('name1')
, ('name2')
, ...
, ('namen')
) as y (name)
on x.name = y.name
when not matched then
insert (name)
values (y.name)
INSERT INTO MyTable (Name)
SELECT Name FROM
(
VALUES ('Name 1'),
('Name 2')
) AS Names(Name)
WHERE Name NOT IN
(
SELECT Name FROM MyTable
)
INSERT IGNORE INTO myTable (column1, column2) VALUES (val1, val2),(val3,val4),(val5,val6);
INSERT IGNORE will allow skip on duplicate values

LIKE using subquery returning multiple rows

There 2 tables emailinfo(id,email) and keywordinfo(id,keyword).
emailinfo contains 80,000 rows and keywordinfo contains 2000 rows.
I want emails from emailinfo table which does not contains keywords from keywordinfo table.
I want not like condition on multiple rows
I have kept all keywords in keywordinfo table
Now I have to fetch all the emails from emailinfo table which not containing any keywords from keywordinfo table.
I want query like following,
select email
from emailinfo
where email not like % (select keyword from keywordinfo)
I have tried following query
SELECT email
FROM emailinfo
join keywordinfo on email like '%' + keyword +'%'**
but its not giving me proper results and is very slow.
How about a slight variation of your second query...?
SELECT Email
FROM EmailInfo
LEFT JOIN KeywordInfo ON Email LIKE '%' + Keyword + '%'
WHERE KeywordInfo.ID IS NULL
Example Data:
CREATE TABLE #EmailInfo (ID INT, Email VARCHAR(50))
INSERT INTO #EmailInfo (ID, Email) VALUES (1, 'test#example.com')
INSERT INTO #EmailInfo (ID, Email) VALUES (2, 'someone#sample.com')
INSERT INTO #EmailInfo (ID, Email) VALUES (3, 'testing#sample.com')
INSERT INTO #EmailInfo (ID, Email) VALUES (4, 'blahblah#blah.com')
INSERT INTO #EmailInfo (ID, Email) VALUES (5, 'example#email.com')
INSERT INTO #EmailInfo (ID, Email) VALUES (6, 'another#goodemail.com')
CREATE TABLE #KeywordInfo (ID INT, Keyword VARCHAR(50))
INSERT INTO #KeywordInfo (ID, Keyword) VALUES (1, 'sample')
INSERT INTO #KeywordInfo (ID, Keyword) VALUES (2, 'test')
SELECT Email
FROM #EmailInfo EmailInfo
LEFT JOIN #KeywordInfo KeywordInfo ON Email LIKE '%' + Keyword + '%'
WHERE KeywordInfo.ID IS NULL
DROP TABLE #EmailInfo
DROP TABLE #KeywordInfo
The following query will returns all the records from emailinfo table which don't have any keyword defined in keywordinfo table.
It's advisable to have an index on emailinfo.email fields to make the query execution faster.
SELECT * FROM emailinfo
where not exists (Select 1 from
keywordinfo where emailinfo.email like '%' + keywordinfo.keyword +'%')
An alternative formulation eliminates the like:
Select
From emailinfo ie
Where not exists (select *
From ki
Where charindex(ki.keyword, ie.email) > 0)
I apologize for the formatting, I'm on a mobile device.
I would also recommend that you change your table structures so each keyword is in a separate row. Then you won't need the like operator.
Instead of trying to come up with a scenario using LIKE, have you considered using FULL TEXT INDEXING?
Pinal Dave has a fairly good introduction on it that can help get you started: http://blog.sqlauthority.com/2008/09/05/sql-server-creating-full-text-catalog-and-index/