Using SQl Server CE; Possible to Insert Only If Not Exists and Delete if Exists? - sql

I have a One Field Table in SQL CE which I need a SQL Statement for. The objective is to Delete the record if it already exists and insert the record if it does not exist. Is the possible with SQL CE?
INSERT INTO Source_Table
SELECT 'myvalue' AS Expr1
WHERE (NOT EXISTS
(SELECT Source_Data
FROM Source_Table AS Source_Table_1
WHERE (Source_Data = 'myvalue')))

Why not just...
DELETE Source_Table WHERE Source_Data = 'myvalue'
GO
INSERT INTO Source_Table (Source_Data) values('myvalue')
I'm not sure what the point of deleting a record and then inserting the same data would be, but this should accomplish it.

If the aim is to literally delete if it exists and only insert it if it does not exist, then you need to do what you've written.
If the aim is to insert if it doesn't exist and replace if it does, Adam's correct that you may as well just always run the delete followed by the insert. I'd run both in the same statement batch, to save overhead.
Were there more than one field, of course you'd do an update, not a delete followed by insert. (But delete followed by insert is how Sybase internally performs updates.)

Related

Copy a table data from one database to another database SQL

I have had a look at similar problems, however none of the answers helped in my case.
Just a little bit of background. I have Two databases, both have the same table with the same fields and structure. Data already exists in both tables. I want to overwrite and add to the data in db1.table from db2.table the primary ID is causing a problem with the update.
When I use the query:
USE db1;
INSERT INTO db2.table(field_id,field1,field2)
SELECT table.field_id,table.field1,table.field2
FROM table;
It works to a blank table, because none of the primary keys exist. As soon as the primary key exists it fails.
Would it be easier for me to overwrite the primary keys? or find the primary key and update the fields related to the field_id? Im really not sure how to go ahead from here. The data needs to be migrated every 5min, so possibly a stored procedure is required?
first you should try to add new records then update all records.you can create a procedure like below code
PROCEDURE sync_Data(a IN NUMBER ) IS
BEGIN
insert into db2.table
select *
from db1.table t
where t.field_id not in (select tt.field_id from db2.table tt);
begin
for t in (select * from db1.table) loop
update db2.table aa
set aa.field1 = t.field1,
aa.field2 = t.field2
where aa.field_id = t.field_id;
end loop;
end;
END sync_Data
Set IsIdentity to No in Identity Specification on the table in which you want to move data, and after executing your script, set it to Yes again
I ended up just removing the data in the new database and sending it again.
DELETE FROM db2.table WHERE db2.table.field_id != 0;
USE db1;
INSERT INTO db2.table(field_id,field1,field2)
SELECT table.field_id,table.field1,table.field2
FROM table;
Its not very efficient, but gets the job done. I couldnt figure out the syntax to correctly do an UPDATE or to change the IsIdentity field within MariaDB, so im not sure if they would work or not.
The overhead of deleting and replacing non-trivial amounts of data for an entire table will be prohibitive. That said I'd prefer to update in place (merge) over delete /replace.
USE db1;
INSERT INTO db2.table(field_id,field1,field2)
SELECT t.field_id,t.field1,t.field2
FROM table t
ON DUPLICATE KEY UPDATE field1 = t.field1, field2 = t.field2
This can be used inside a procedure and called every 5 minutes (not recommended) or you could build a trigger that fires on INSERT and UPDATE to keep the tables in sync.
INSERT INTO database1.tabledata SELECT * FROM database2.tabledata;
But you have to keep length of varchar length larger or equal to database2 and keep the same column name

Creating a Trigger which will insert record in a table on update of another table

Suppose I have tables T1 and T2
Columns of T1 -->Value
Columns of T2 -->OldValue NewValue
What I require is a trigger which will insert a record in T2 on updation of T1 , I need to know the old value and new value also , I have never used triggers before , so can any help me with this , how do I go about creating this trigger.Is it possible ,thanks.
Well, you start writing a trigger with CREATE TRIGGER:
CREATE TRIGGER NameOfTheTriggerPlease
…
The table that should trigger the additional action is T1 so the trigger should be defined ON that table:
CREATE TRIGGER T1OnUpdate /* that's just an example,
you can use a different name */
ON T1
…
The action that the trigger should be invoked on is UPDATE and the timing is AFTER the update, so…
CREATE TRIGGER T1OnUpdate
ON T1
AFTER UPDATE
…
Now's the time to introduce the body of the trigger, i.e. the statements that should actually be executed by the trigger. You introduce the body with the AS keyword followed by the statements themselves.
In your case, there would be just one statement, INSERT, which is obvious. What's not so obvious is how we are going to access the old and the new values. Now, SQL Server offers you two virtual tables, INSERTED and DELETED, and you can easily guess that the former contains all the new values and the latter the old ones.
These tables have the same structure as the table the trigger is assigned to, i.e. T1. They only contain rows that were affected by the particular UPDATE statement that invoked the trigger, which means there may be more than one. And that, in turn, means that you need to have some primary key or a unique column (or a set of columns) in your T1 table that you can use in the trigger to match deleted and inserted rows. (In fact, you might also need your T2 table to have a column that would reference the T1's primary key, so you could later establish which row of T1 had which values stored in T2.)
For the purposes of this answer, I'm going to assume that there's a primary key column called PK and a foreign key column of the same name in T2. And the INSERT statement then might look like this:
CREATE TRIGGER T1OnUpdate
ON T1
AFTER UPDATE
AS
INSERT INTO T2 (PK, OldValue, NewValue)
SELECT i.PK, i.Value, d.Value
FROM INSERTED i INNER JOIN DELETED d ON i.PK = d.PK
One last (but not least) thing to remember: the entire CREATE TRIGGER statement should be the only one in the batch, i.e. there should be no statements preceding the CREATE TRIGGER keywords (but you can put comments there) and, likewise, everything after the AS keyword is considered part of the trigger's body (but you can put the GO delimiter to indicate the end of the statement if you are running the script in SQL Server Management Studio, for instance).
Useful reading:
CREATE TRIGGER (Transact-SQL)
I'm not going to build the whole thing for you (no fun, right?) but I can point you in the right direction
create trigger logUpdate
on T1
After update
as
begin
insert into T2...
--here is just an example
select * from deleted --the DELETED table contains the OLD values
select * from inserted --the INSERTED table contains the NEW values
end
remember that DELETED and INSERTED are internal tables that contains old and new values. On a update trigger, they both exist. On a insert trigger, DELETED will be null because there is nothing being delete. Same logic on a delete trigger, the INSERTED will be empty
EDIT:
answering your question: no matter how many fields you update, your DELETED and INSERTED tables you have all the columns of all the rows affected. Of course, if you update only one column, all the other will have the same value on DELETED and INSERTED
create trigger T_UPD_T1
on T1 FOR update
as
insert into T2 select deleted.value, inserted.value from inserted, deleted

Using OUTPUT with joined tables

Why doesn't the following work?
INSERT INTO dbo.Pending_Break
(Pending_Pod_ID, Break_Date_Time, Break_Length, Booked_Length)
OUTPUT INSERTED.Pending_BH_ID -- This is the inserted identity
, INSERTED.Pending_Pod_ID
, INSERTED.Break_Name
, INSERTED.Break_Date_Time
, pb.PENDING_BH_ID -- complains on this one
INTO #InsertedPendingBreaks
SELECT ippod.Pending_Pod_ID,
pb.Break_Date_Time
pb.break_length,
0
FROM PendingBreak pb
JOIN InsertedPod ippod ON ...
Can I not use anything other than Inserted or Deleted in the OUTPUT clause?
Can I not use anything other than Inserted or Deleted in the OUTPUT
clause?
No you can't. At least not with an insert. In SQL Server 2008 you can convert your insert to a merge statement instead and there you can use values from the source table in the output clause.
Have a look at this question how to do that in SQL Server 2008. Using merge..output to get mapping between source.id and target.id
The inserted and deleted tables are available only in DML triggers. I'm not sure if you just pulled a code snippet out of a trigger, but if that is a standalone batch then it won't work.
Also, there is no updated table. An update is a delete and then an insert for this. deleted contains the old data and inserted contains the new data on an UPDATE.

Delete and Insert or Select and Update

We have a status table. When the status changes we currently delete the old record and insert a new.
We are wondering if it would be faster to do a select to check if it exists followed by an insert or update.
Although similar to the following question, it is not the same, since we are changing individual records and the other question was doing a total table refresh.
DELETE, INSERT vs UPDATE || INSERT
Since you're talking SQL Server 2008, have you considered MERGE? It's a single statement that allows you to do an update or insert:
create table T1 (
ID int not null,
Val1 varchar(10) not null
)
go
insert into T1 (ID,Val1)
select 1,'abc'
go
merge into T1
using (select 1 as ID,'def' as Val1) upd on T1.ID = upd.ID --<-- These identify the row you want to update/insert and the new value you want to set. They could be #parameters
when matched then update set Val1 = upd.Val1
when not matched then insert (ID,Val1) values (upd.ID,upd.Val1);
What about INSERT ... ON DUPLICATE KEY? First doing a select to check if a record exists and checking in your program the result of that creates a race condition. That might not be important in your case if there is only a single instance of the program however.
INSERT INTO users (username, email) VALUES ('Jo', 'jo#email.com')
ON DUPLICATE KEY UPDATE email = 'jo#email.com'
You can use ##ROWCOUNT and perform UPDATE. If it was 0 rows affected - then perform INSERT after, nothing otherwise.
Your suggestion would mean always two instructions for each status change. The usual way is to do an UPDATE and then check if the operation changed any rows (Most databases have a variable like ROWCOUNT which should be greater than 0 if something changed). If it didn't, do an INSERT.
Search for UPSERT for find patterns for your specific DBMS
Personally, I think the UPDATE method is the best. Instead of doing a SELECT first to check if a record already exists, you can first attempt an UPDATE but if no rows are affected (using ##ROWCOUNT) you can do an INSERT.
The reason for this is that sooner or later you might want to track status changes, and the best way to do this would be to keep an audit trail of all changes using a trigger on the status table.

Need some help with Sql Server and a simple Trigger

I wish to make a trigger but i'm not sure how to grab the data for whatever caused the trigger.
I have a simlpe table.
FooId INT PK NOT NULL IDENTITY
Name VARCHAR(100) NOT NULL
I wish to have a trigger so that when an UPDATE, INSERT or DELETE occurs, i then do the following.
Pseduocode
IF INSERT
Print 'Insert' & Name
ELSE IF UPDATE
Print 'Update' & FooId & Name
ELSE IF DELETE
Print 'Delete' & FooId & Name
Now, I know how to make a trigger for a table.
What i don't know how to do is figure out the values based on what the trigger type is.
Can anyone help?
Edit: Not sure if it helps, but db is Sql Server 2008
the pseudo table "inserted" contains the new data, and "deleted" table contains the old data.
You can do something like
create trigger mytrigger on mytable for insert, update, delete
as
if ( select count(*) from inserted ) > 0
-- insert or update
select FooId, Name from inserted
else
-- delete
select FooId, Name from deleted
To clarify all the comments made by others, on an insert, the inserted table contains data and deleted is empty. On a delete, the situation is reversed. On an update, deleted and inserted contain the "before" and "after" copy of any updated rows.
When you are writing a trigger, you have to account for the fact that your trigger may be called by a statement that effects more than one row at a time.
As others have pointed out, you reference the inserted table to get the values of new values of updated or inserted rows, and you reference the deleted table to get the value of deleted rows.
SQL triggers provide an implicitly-defined table called "inserted" which returns the affected rows, allowing you to do things like
UPDATE mytable SET mytimestamp = GETDATE() WHERE id IN (SELECT id FROM inserted)
Regarding your code sample, you'll want to create separate INSERT, UPDATE and DELETE triggers if you are performing separate actions for each.
(At least, this is the case in SQL Server... you didn't specify a platform.)
On 2008, there is also MERGE command. How do you want to handle it?
Starting from 2008, there are four commands you can modify a table with:
INSERT, UPDATE, DELETE, and MERGE:
http://blogs.conchango.com/davidportas/archive/2007/11/14/SQL-Server-2008-MERGE.aspx
http://sqlblogcasts.com/blogs/grumpyolddba/archive/2009/03/11/reasons-to-move-to-sql-2008-merge.aspx
What do you want your trigger to do when someone issues a MERGE command against your table?