SQL Delete Statement (Where <Field> Not In) - sql-server-2005

How can I delete a specific row on a table only if its data is not used by another table anymore?
Lets say I have a [schedule] table and [scheduletype] table. If a specific [scheduletype] is not found in [schedule].[type] field of the [schedule] table then it will be removed from the [scheduletype] table.
BTW I am using SQL Server 2005.

Try this (assuming the relevant field is called id in schedule):
DELETE FROM scheduletype WHERE id NOT IN (select a.type FROM schedule a)

Well, first is you should probably set up a foreign key constraint to ensure deletes can't happen if the tables are logically related. Read more here: http://msdn.microsoft.com/en-us/library/ms175464(v=SQL.90).aspx
For the delete, you'd do this:
delete scheduletype
where type not in (select type from schedule)

Related

SQL Update statement that deletes rows if key clash

I have a table that has two columns Hotel_Guest_ID and Guest_ID that links Guest records to the Hotel details of that guest. The table has the constraint that each pair needs to be unique.
I now have a second table of Prime_ID and Duplicate_ID that was generated after cleaning up the Guest table of duplicates. I would like to go through the Booking table and if the Hotel.Guest_ID is found as a Duplicate_ID, to then replace it with Prime_ID.
update b
set h.Guest_ID = gd.Prime_ID
from Hotel as h
join Guest_Duplicates as gd
on h.Guest_ID = gd.Duplicate_ID
However this fails as often a Prime_ID already has a record with a specific Guest, at which point I want to just delete this row instead of updating it.
Is there a nice way to do this in a single pass or would I have to delete potential clash rows first, then update in a second query?
What you are looking for is a MERGE statement. You can insert, update and delete using a single statement. Here's an example -
MERGE Table1 AS t1
USING Table2 AS t2
ON t1.GuestID = t2.DuplicateID
WHEN MATCHED AND (any condition)
THEN DELETE
WHEN MATCHED
THEN UPDATE SET (assign statement)
WHEN NOT MATCHED
THEN
INSERT(column names)
VALUES(values to be inserted);

Creating a trigger in order to maintain an intermediate table integrity

I've created a database with the following diagram:
http://imagizer.imageshack.us/v2/800x489q90/440/o1yu.png
The TrainerPokemon table represents an occurrence of a pokemon (that belongs to a trainer), while the Pokemon table represents a pokemon 'specie'. One certain specie of pokemon may have access to certain abilities, but an occurrence of this pokemon may carry only one ability (column AbilityID on the TrainerPokemon table).
Here's my problem: I was trying to create a trigger in order to prevent that any other ability (different from what is specified in the PokemonAbility table) is inserted/updated to a register in the TrainerPokemon table, but I did not have success.
Does anyone has any idea for a trigger? New ideas for this database model are welcome as well.
(Important Note: I am using SQL Server 2012)
Something like this (typing off the top of my head):
CREATE TRIGGER trg_pok_abil ON TrainerPokemon FOR UPDATE, INSERT
AS
BEGIN
IF EXISTS (
SELECT *
FROM inserted
WHERE inserted.AbilityID NOT (
SELECT AbilityID
FROM PokemonAbility
WHERE PokemonAbility.PokemonID = inserted.PokemonID
)
BEGIN
ROLLBACK
END
END
You could add a two column foreign key constraint between pokemonability and trainerpokemon on pokemonid, abilityid.
HTH

How to Update a Single record despite multiple Occurances of the same ID Number?

I have a table that looks like the below table:
Every time the user loan a book a new record is inserted.
The data in this table is derived or taken from another table which has no dates.
I need to update this tables based on the records in the other table: Meaning I only need to update this table based on what changes.
Example: Lets say the user return the book Starship Troopers and the book return is indicated to Yes.
How do I update just that column?
What I have tried:
I tried using the MERGE Statement but it works only with unique rows of data, meaning you get an error if the same ID appears more than once.
I also tried using a basic UPDATE Statement and a JOIN but that's not going well.
I am asking because I have ran out of ideas.
Thanks for reading
If you need to update BooksReturn in target table based on the same column in source table
UPDATE t
SET t.booksreturn = s.booksreturn
FROM target t JOIN source s
ON t.userid = s.userid
AND t.booksloaned = s.booksloaned
Here is SQLFiddle demo
You can do this by simple Update & Insert statement.....
Two table A & B
From B you want to insert data into A if not exists other wise Update that data....
,First Insert into temp table....
SELECT *
INTO #MYTEMP
FROM B
WHERE BOOKSLOANED NOT IN (SELECT BOOKSLOANED
FROM A)
,Second Check data and insert into A.
INSERT INTO A
SELECT *
FROM #MYTEMP
And at last write one simple update statement which update all data of A. If any change then it also reflect to that data otherwise data as it is.
You can also update from #MYTEMP table.

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

Foreign Key reference in mysql innodb

Simply put: I have a table with 2 columns: one is username and other is nickname.
I have another table where I have 2 columns: one is username and other is countNicknames.
I want countNicknames to contain the number of nicknames each user has (and whenever I insert a new nickname to the table1, the value under table2.countNicknames will automatically update.
Can you please write down how to construct the second table to reference the first one?
Why not just count when you need the value?
I want countNicknames to contain the number of nicknames each user has (and whenever I insert a new nickname to the table1, the value under table2.countNicknames will automatically update.
This is effectively what a view will do.
CREATE OR REPLACE VIEW user_nickname_count AS
SELECT t.username,
COUNT(*) 'countNicknames'
FROM TABLE t
GROUP BY t.username
A view looks like a table, so you cah join to it if needed. And the only overhead is that it effectively is just a SELECT query being run - the values are calculated on demand, rather than having to setup triggers.
For more info on views, see the documentation.
Well, #Lasse's suggestion is better, but ... there is two other another options...
Does MySql have triggers? If it does, then you would add an Insert, Update, Delete trigger on the first table that updates (or inserts or deletes as necessary) the second table's CountNickNames attribute every time a record is inserted, Updated or deleted from the first table...
Create Trigger NickNameCountTrig On NickNameCountTable
For Insert, Update, Delete
As
Update nct Set
CountNickNames =
(Select Count() From FirstTable
Where Name = nct.Name)
From NickNameCountTable nct
Where Name In (Select Distinct Name from inserted
Union
Select Distinct Name From deleted)
-- -----------------------------------------------
Insert NickNameCountTable (Name, CountNickNames)
Select name, count() from FirstTable ft
Where Not Exists
(Select * From NickNameCountTable
Where Name = ft.Name)
-- ------ This is optional -----------------------
Delete NickNameCountTable
Where CountNickNames = 0
Does MySql have indexed views (or some equivilent)? apparently not - so never mind this option ....