INSERT statement will not let me use IF NOT EXISTS - asp.net

I have an insert statement that I can't get to work the way I want it to. It's on a vb.net page. This is on a VB.net page and I'm using SQL Server 2005 for my database.
Dim strSQL As String = "IF NOT EXISTS
(SELECT Title From Picklist)
BEGIN INSERT INTO Picklist (Title, Data)
VALUES (#Title, #Data);
INSERT INTO Marketing
(ProductID, MarketingTypeID, MarketingTitle, MarketingData)
VALUES (#ProductID, 9, 'Video', scope_identity()) END"
I don't get an error and nothing gets inserted into the database. If I try putting the END at the end of the first INSERT statement then I get an error saying that MarketingData is NULL and cannot be inserted.
But if I take out the IF NOT EXISTS from the statement, everything gets inserted perfectly. What am I doing wrong here?
UPDATE: Is it correct to write the statement like this?
INSERT INTO Marketing
SELECT (#ProductID, #MarketingTypeID, #MarketingTitle, #MarketingData)
WHERE NOT EXISTS
(SELECT * FROM Marketing)

Your IF NOT EXISTS(SELECT * FROM Picklist) will skip the insert if any rows at all exist in Picklist.
From your description of what happens when you change the position of the END it seems there are rows in the table.
I assume in fact you are trying to do an UPSERT. What version of SQL Server are you on? If 2008 look into MERGE
;WITH Source(Title, Data) AS
(
SELECT #Title, #Data
)
MERGE Picklist AS T
USING Source S
ON (T.Title = S.Title)
WHEN NOT MATCHED BY TARGET THEN
INSERT (Title, Data)
VALUES (#Title, #Data)
;
IF (##ROWCOUNT <> 0)
INSERT INTO Marketing
(ProductID, MarketingTypeID, MarketingTitle, MarketingData)
VALUES (#ProductID, 9, 'Video', scope_identity())

Related

SQLite insert into table using the id from an inner insert

I'm trying to insert a parent and child at the same time.
My idea is to insert the parent, get the id using SELECT last_insert_rowid() AS [Id] and use this id to insert the child
I can get each part of this working independently but not as a whole. This is what I currently have:
INSERT INTO ParentTable (Col1)
VALUES( 'test')
SELECT last_insert_rowid() AS [Id]
The above works - so far so good. Now I want to use the result of this in the child insert. This is what I have:
INSERT INTO ChildTable (col1, col2, ParentId)
VALUES( 1, 2, SELECT Id FROM (
INSERT INTO ParentTable (Col1)
VALUES( 'test')
SELECT last_insert_rowid() AS [Id]
);
I get this error:
near "SELECT": syntax error:
Can anyone point me in the right direction?
You can't use INSERT in SELECT statement. You should first insert and then use last inserted id:
INSERT INTO ParentTable (Col1) VALUES( 'test');
INSERT INTO ChildTable (col1, col2, ParentId)
VALUES(1,2, (SELECT last_insert_rowid()));
Since you want to insert many records with parent ID, here is a workaround:
BEGIN TRANSACTION;
CREATE TEMPORARY TABLE IF NOT EXISTS temp(id integer);
DELETE FROM temp;
INSERT INTO ParentTable (Col1) VALUES( 'test');
INSERT INTO temp SELECT last_insert_rowid();
INSERT INTO ChildTable (col1, col2, ParentId)
VALUES(1,2, (SELECT id FROM temp LIMIT 1));
.............
COMMIT;
DROP TABLE temp;
Or you can create a permanent table to this effect.
That SQLite.Net PCL driver assumes that you use the ORM: inserting an object will automatically read back and assign the autoincremented ID value.
If you're using raw SQL, you have to manage the last_insert_rowid() calls yourself.
Your idea is correct, but you have to do everything in separate SQL statements:
BEGIN; -- better use RunInTransaction()
INSERT INTO Parent ...;
SELECT last_insert_rowid(); --> store in a variable in your program
INSERT INTO Child ...;
...
END;
(SQLite is an embedded database and has no client/server communication overhead; there is no reason to try to squeeze everything into a single statement.)

"Insert if not exists" statement in SQLite

I have an SQLite database. I am trying to insert values (users_id, lessoninfo_id) in table bookmarks, only if both do not exist before in a row.
INSERT INTO bookmarks(users_id,lessoninfo_id)
VALUES(
(SELECT _id FROM Users WHERE User='"+$('#user_lesson').html()+"'),
(SELECT _id FROM lessoninfo
WHERE Lesson="+lesson_no+" AND cast(starttime AS int)="+Math.floor(result_set.rows.item(markerCount-1).starttime)+")
WHERE NOT EXISTS (
SELECT users_id,lessoninfo_id from bookmarks
WHERE users_id=(SELECT _id FROM Users
WHERE User='"+$('#user_lesson').html()+"') AND lessoninfo_id=(
SELECT _id FROM lessoninfo
WHERE Lesson="+lesson_no+")))
This gives an error saying:
db error near where syntax.
If you never want to have duplicates, you should declare this as a table constraint:
CREATE TABLE bookmarks(
users_id INTEGER,
lessoninfo_id INTEGER,
UNIQUE(users_id, lessoninfo_id)
);
(A primary key over both columns would have the same effect.)
It is then possible to tell the database that you want to silently ignore records that would violate such a constraint:
INSERT OR IGNORE INTO bookmarks(users_id, lessoninfo_id) VALUES(123, 456)
If you have a table called memos that has two columns id and text you should be able to do like this:
INSERT INTO memos(id,text)
SELECT 5, 'text to insert'
WHERE NOT EXISTS(SELECT 1 FROM memos WHERE id = 5 AND text = 'text to insert');
If a record already contains a row where text is equal to 'text to insert' and id is equal to 5, then the insert operation will be ignored.
I don't know if this will work for your particular query, but perhaps it give you a hint on how to proceed.
I would advice that you instead design your table so that no duplicates are allowed as explained in #CLs answer below.
For a unique column, use this:
INSERT OR REPLACE INTO tableName (...) values(...);
For more information, see: sqlite.org/lang_insert
insert into bookmarks (users_id, lessoninfo_id)
select 1, 167
EXCEPT
select user_id, lessoninfo_id
from bookmarks
where user_id=1
and lessoninfo_id=167;
This is the fastest way.
For some other SQL engines, you can use a Dummy table containing 1 record.
e.g:
select 1, 167 from ONE_RECORD_DUMMY_TABLE

Inserting data from one table to the next in sql

I have two tables with fields as shown below :-
tbl_emp --> id(auto generate, auto increment, primary key),name, dob
tbl_login --> id(refers to id in tbl_emp, primary key), password
I have a web form which reads the name, password and date of birth(dob), and a submit button. On pressing the submit button, the data is inserted into the first table, and also to the second table. It would be easy to insert data to the second column if I had a way to access the "id" field from the first table.
The query I have is :-
insert into tbl_emp (name,dob) values(#name, #dob);
insert into tbl_login (id,password) values((select id from tbl_emp where id=(select id from tbl_emp where id=id)), #password)
The problem that I encounter with the above coeds is :
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
The statement has been terminated.
You could use the SCOPE_IDENTIY function:
insert into tbl_emp (name,dob) values(#name, #dob);
insert into tbl_login (id,password)
select id, #password
from tbl_emp
where id = SCOPE_IDENTITY();

bulk insert using insert...select in sqlite?

I have a list of users who should receive the message. They are in the table subscribe. Now I'd like to insert a message for every one of these users. My query is
insert into message(user, type, theId)
select (select user from subscribe_message), #type, #id
At the moment it is empty. I get the error message.user may not be NULL. Shouldn't it not insert any rows? When I have more than one row it inserts the first row only. How do I write this so it will insert 0 to many rows?
Try this
INSERT INTO message ( user, type, theId )
SELECT subscribe_message.user, #type, #id
FROM subscribe_message

Insert an AVG() Value from a table into the same table

I have one table named Test with columns named ID,Name,UserValue,AverageValue
ID,Name,UserValue,AverageValue (As Appears on Table)
1,a,10,NULL
2,a,20,NULL
3,b,5,NULL
4,b,10,NULL
5,c,25,NULL
I know how to average the numbers via (SELECT Name, AVG(UserValue) FROM Test GROUP BY Name)
Giving me:
Name,Column1(AVG(Query)) (As Appears on GridView1 via databind when I run the website)
a,15
b,7.5
c,25
What I need to do is make the table appear as such by inserting the calculated AVG() into the AverageValue column server side:
ID,Name,UserValue,AverageValue (As Appears on Table)
1,a,10,15
2,a,20,15
3,b,5,7.5
4,b,10,7.5
5,c,25,25
Conditions:
The AVG(UserValue) must be inserted into Test table AverageValue.
If new entries are made the AverageValue would be updated to match AVG(UserValue).
So what I am looking for is a SQL command that is something like this:
INSERT INTO Test (AverageValue) VALUES (SELECT Name, AVG(UserValue) FROM Test GROUP BY Name)
I have spent considerable amount of time searching on google to find an example but have had no such luck. Any examples would be greatly appreciated. Many thanks in advance.
Try this:
with toupdate as (
select t.*, avg(uservalue) over (partition by name) as newavg
from test t
)
update toupdate
set AverageValue = newavg;
The CTE toupdate is an updatable CTE, so you can just use it in an update statement as if it were a table.
I believe this will do the trick for you. I use the merge statement a lot! It's perfect for doing things like this.
Peace,
Katherine
use [test_01];
go
if object_id (N'tempdb..##test', N'U') is not null
drop table ##test;
go
create table ##test (
[id] [int] identity(1, 1) not null,
[name] [nvarchar](max) not null,
[user_value] [int] not null,
[average_value] [decimal](5, 2),
constraint [pk_test_id] primary key([id])
);
go
insert into ##test
([name], [user_value])
values (N'a',10),
(N'a',20),
(N'b',5),
(N'b',10),
(N'c',25);
go
with [average_builder] as (select [name],
avg(cast([user_value] as [decimal](5, 2))) as [average_value]
from ##test
group by [name])
merge into ##test as target
using [average_builder] as source
on target.[name] = source.[name]
when matched then
update set target.[average_value] = source.[average_value];
go
select [id], [name], [user_value], [average_value] from ##test;
go

Resources