I have two tables
Travel Table
tid | tname | countryid | status
1 | a | 1 |
PassengerTravel
tid | passengerid
1 | 1
1 | 2
i want update status column in table 1 if insert in passenger Travel table
and update status column if print the travel application for them
Can you do with your code ?
the first one it can use trigger to manage it.
the second you print with your application right ?
why not let the code to update this.
Related
Consider data existing in a table:
Customers
| CustomerID | Name | Status |
|------------|-----------------|--------------------|
| 1 | Ian Boyd | Killed |
| 2 | Shelby Hawthorn | Booked |
And rows i would like to MERGEd into the Customers table:
| CustomerID | Name | Status |
|------------|-----------------|--------------------|
| 1 | Ian Boyde | Waiting | name has 'e' on the end
| 2 | Shelby Blanken | Waiting | different last name
| 3 | Jessica Bogden | Waiting | totally new row
So i can come up with approximate psuedocode MERGE statement:
MERGE Customers USING (
SELECT CustomerID, Name, 'Waiting' FROM Staging) foo
ON Customers.CustomerID = foo.CustomerID
WHEN MATCHED THEN
UPDATE SET Name = foo.Name, Status = foo.Status
WHEN NOT MATCHED BY TARGET THEN
INSERT (Name, Status)
VALUES (Name, Status);
And that would MERGE them:
| CustomerID | Name | Status |
|------------|-----------------|--------------------|
| 1 | Ian Boyde | Waiting | Last name spelling updated
| 2 | Shelby Blanken | Waiting | Last name changed
| 3 | Jessica Bogden | Waiting | New row added
But only UPDATE some rows
Except a caveat is that i don't want update any existing rows for customers who are Booked. In other words i want the final results to be:
| CustomerID | Name | Status |
|------------|-----------------|--------------------|
| 1 | Ian Boyde | Waiting | updated existing row spelling
| 2 | Shelby Hawthorn | Booked | not updated because they're booked
| 3 | Jessica Bogden | Waiting | inserted new row
My first guess would for the UPDATE to have a where clause:
MERGE Customers USING (
SELECT CustomerID, Name, 'Waiting' FROM Staging) foo
ON Customers.CustomerID = foo.CustomerID
WHEN MATCHED THEN
UPDATE SET Name = foo.Name, Status = foo.Status
WHERE Status <> 'Booked' -- <--------- it's the matching row; but don't update it
WHEN NOT MATCHED BY TARGET THEN
INSERT (Name, Status)
VALUES (Name, Status);
But that's not a valid syntax.
My second guess would be to add the criteria to the ON clause:
MERGE Customers USING (
SELECT CustomerID, Name, 'Waiting' FROM Staging) foo
ON Customers.CustomerID = foo.CustomerID
AND Customers.Status <> 'Booked'
WHEN MATCHED THEN
UPDATE SET Name = foo.Name, Status = foo.Status
WHERE Status <> 'Booked' --it's the matching row; but don't update it
WHEN NOT MATCHED BY TARGET THEN
INSERT (Name, Status)
VALUES (Name, Status);
But now the row would not match, and they would get inserted under the not matched by target rule:
| CustomerID | Name | Status |
|------------|-----------------|--------------------|
| 1 | Ian Boyde | Waiting | updated existing row
| 2 | Shelby Hawthorn | Booked | not matched bcause booked
| 3 | Jessica Bogden | Waiting | inserted new row
| 4 | Shelby Blanden | Waiting | Mistakenly inserted because not matched by target
What's the way out of the conundrum?
The key is that you want to make sure that the record falls into the MATCHED logic, otherwise it will generate a new row via the NOT MATCHED logic.
To do this, using your code, we add your criteria to the MATCHED logic:
MERGE Customers USING (
SELECT CustomerID, Name, 'Waiting' FROM Staging) foo
ON Customers.CustomerID = foo.CustomerID
WHEN MATCHED AND Customers.Status <> 'Booked' THEN
UPDATE SET Name = foo.Name, Status = foo.Status
WHEN NOT MATCHED BY TARGET THEN
INSERT (Name, Status)
VALUES (Name, Status);
This tells the merge to match everything on CustomerID. When it finds a match, you then tell it to only run the update if the Status <> 'Booked'
Merge statements are driven by the USING clause.
Rows in the USING that do match existing rows cause existing rows to update.
Rows in the USING that do not match existing rows cause new rows to be created
Rows that are not in the USING clause cannot affect rows in the db
If you do not want an existing row to be updated, ensure its matching row never makes it into the result set presented by the statement in the USING. This may mean doing a join in the USING. This is fine
Example:
MERGE Customers USING (
SELECT
s.CustomerID,
s.Name,
'Waiting' as Stat
FROM
Staging s
INNER JOIN Existing e on s.CustomerId = e.CustomerId
WHERE
e.Status <> 'Booked' --ignore all existing booked rows
) foo
...
This join inside the using statement ensures that the staging row that relates to the existing "Booked" row, never makes it into the result set produced by the USING. It hence cannot cause either an update or an insert
I am having two columns in table
InventoryId | RevisionId
-------------------------
1 | 1
2 | 1
2 | 2
2 | 2
3 | 1
3 | 2
3 | 3
3 | 3
but from now on I want to prevent following records
2 | 2
2 | 2
3 | 3
3 | 3
So I thought to create a unique index on these two columns
but the table having so much existing data. So anything we can do this situation.
Any suggestion?
you can use a trigger to prevent new rows being added with duplicate values
look at this example
create trigger TR_UI_YourTable on YourTable
for update, insert as
begin
set nocount on
if exists (select 1 from inserted i where i.InventoryId = i.RevisionId)
begin
;throw 99001, 'no dupes allowed anymore...', 1
end
end
A better solution would be to move the duplicates to a seperate table for history, and then add a check constraint on these 2 columns
EDIT
you could do it by an check constraint like this
alter table yourtable
add constraint chk_dupes
check ((InventoryId <> RevisionId) or (id <= 12345))
where 12345 is the highest value of the column id now.
You will have to test it a bit if it works on all situations.
Also, it will only work if all new rows have a value in id that is larger then the current highest value (12345 in my example)
I have 3 tables, med_list, med_receive and med_issue.
med_list
-----------------------------------
| med_id | med_name | med_balance |
-----------------------------------
med_receive (med_amount is the amount received):
-----------------------------------
| med_id | med_batch | med_amount |
-----------------------------------
med_issue (med_amount here is the amount issued):
-----------------------
| med_id | med_amount |
-----------------------
Now the med_balance in table med_list should be equal to sum of received med - sum of issued med.
The user directly adds into the receive and issue table.
My question is: can I automate the update of the med_balance for all med?
For example:
Let's say we have med with name X and its balance is 0. If the user enters a receive of 100 tablets for that med, the med_balance should automatically be updated to 100.
Thank you for your help.
write a before insert trigger on the driving table.
In the Before Insert trigger update the value.
I'm posting here because I have not been able to find what I'm looking for, or even the correct keywords to search on. If there are better answers that I was unable to find, please feel free to point me in that direction.
However I have two tables which Table 1 is the primary table, and I need to SELECT all records out of it and add an additional column in the SELECT that returns if any related records in Table 2.
I have boiled the problem down to the following and any help would be much appreciated.
Table 1 has a many relationship to Table 2
SELECT must return all rows from Table 1
SELECT must have an additional column (preferably a BOOLEAN/INTEGER) column that represents if there are any related records in Table 2.
SELECT must work in both Access and SQL Server
TABLE 1
--------
GUID1 | DATA FIELD | DATA FIELD
GUID2 | DATA FIELD | DATA FIELD
GUID3 | DATA FIELD | DATA FIELD
TABLE 2
--------
GUID1 | TABLE 1 GUID | DATA FIELD | DATA FIELD
GUID2 | TABLE 1 GUID | DATA FIELD | DATA FIELD
GUID3 | TABLE 2 GUID | DATA FIELD | DATA FIELD
GUID4 | TABLE 2 GUID | DATA FIELD | DATA FIELD
SELECTED TABLE ( 1 JOINED ON TABLE 2 )
--------
GUID1 | DATA FIELD | DATA FIELD | 1 (EXISTS IN TABLE 2)
GUID2 | DATA FIELD | DATA FIELD | 1 (EXISTS IN TABLE 2)
GUID3 | DATA FIELD | DATA FIELD | 0 (DOES NOT EXISTS IN TABLE 2)
You can use a LEFT OUTER JOIN with a case statement to check if the data in the second table is null. Here is an example:
SELECT First.*,
CASE
WHEN Second.DATA3 IS NULL
THEN 0
ELSE 1
END
FROM First
LEFT OUTER JOIN Second ON First.GUID1 = Second.GUID1
SQL Fiddle: http://sqlfiddle.com/#!6/ab17a/1
There are 10 rooms with a set of inventory items. When an item is added/deleted from a room a new row gets inserted to a MS-SQL table. I need the latest update for each room.
Take this series of inserts:
id| room| descriptor1| descriptor2| descriptor3|
1 | A | blue | 2 | large |
2 | B | red | 1 | small |
3 | A | blue | 1 | large |
What the resulting table needs to show:
room| descriptor1| descriptor2| descriptor3|
A | blue |1 | large |
B | red |1 | small |
Ideally, I would write a trigger that would update a room status table. I could then just query the room status table (Select *) to obtain the result. However, this table does not belong to me, I only have read access to a constantly updated table. I need to poll periodically or when I need a report.
How do I do this in MS-SQL? I have some inkling of how I would do it to obtain the status of just one room something like:
SELECT descriptor1, descriptor2, descriptor3
FROM myTable mt1
WHERE id = (SELECT MAX(id)
from myTable mt2
WHERE room = 'A'
);
Since I have 10 rooms i would need to do this query 10 times. Can this be narrowed down to a single query? What happens when there are 100 rooms? Is there a better way?
Thanks!
Matt
You were very close:
SELECT descriptor1, descriptor2, descriptor3
FROM myTable mt1
WHERE id in (SELECT MAX(id)
From myTable
Group By room
);
Instead of creating a trigger to update a static table, you should look into creating a view.