SQL - Selecting a field from another table using a primary key in a trigger - sql

I have two tables in my database, one is Transactions and the other is TransactionHistories. The latter is essentially an auditing table, whereby a trigger executes on insert, update and delete on Transactions to capture a screenshot of the data.
I am successfully retrieving all of the data stored in the Transactions table where the columns match, but the difficulty comes where I am trying to retrieve data from another table using a foreign key. For instance:
The transaction table has a field "TransactionType_TransactionTypeId", but in the audit table we wish to store its 'name' equivalent as "TransactionTypeName". This needs to be populated from the "TransactionTypes" table, which has the fields "TransactionTypeId" and "Name".
I am struggling to write a query to retrieve this as we wish. I am trying something similar to the following but having little success:
SELECT #TransactionTypeName=Name
FROM TransactionTypes
WHERE inserted.TransactionType_TransactionTypeId=TransactionTypes.TransactionTypeId;
I'm assuming that is a syntactic nightmare. If someone could point me in the right direction I would be extremely grateful!

well to get a name you should do the following
select #TransactionTypeName = TT.Name
from inserted as i
left outer join TransactionTypes as TT on TT.TransactionTypeId = i.TransactionType_TransactionTypeId
but you have to know that inserted table can have more than one row, and you are getting value for only one row.

Related

Remove Records from Tables Selectively Based on Variable

Scenario:
I need to write an SQL script which will remove all records from some or all tables in a database with around 100 tables.
Some tables are 'data' tables, some are 'lookup' tables. There is nothing in their names to indicate which they are.
Sometimes I will want the script to only remove records from the 'data' tables, on other occasions I will want to use it to remove data from all tables.
The records have to be removed from the tables in a very specific order to prevent foreign key constraint violations.
My original idea was to create a variable at the start of the script - something like #EmptyLookupTables - which I could set to true or false, and then I could wrap the DELETE statements in an IF... statement so that they were only executed if the value of the variable was true.
However, due to the foreign key constraints I need to include the GO command after just about every DELETE statement, and variables are not persisted across these batches.
How can I write a script which deletes records from my tables in the correct order but skips over certain tables based on the value of a single variable? The database is in Microsoft SQL Server 2016.
The only way I know of doing this without writing a parser for DDL in TSQL is to turn it on its head.
Create a new database with the same schema; populate the lookup tables, but without the records you don't want. Then populate the data tables, but again leave out the records you don't want. Finally, rename or delete the old database, and rename the new database to the original name.
It's still hard, though.
Create a #temp table and store your variable in it, it will persist across GO separated batches. Then just check the temp table inside every batch.
SELECT #EmptyLookupTables AS EmptyLookupTables INTO #tmp
GO
DECLARE #EmptyLookupTables BIT
SELECT #EmptyLookupTables = EmptyLookupTables FROM #tmp
DELETE FROM YourLookupTable WHERE #EmptyLookupTables = 1
GO
or you can even join directly on #temp table in delete command
DELETE l FROM YourLookupTable l
INNER JOIN #tmp t ON t.EmptyLookupTables = 1

Oracle SQL merge tables without specifying columns

I have a table people with less than 100,000 records and I have taken a backup of this table using the following:
create table people_backup as select * from people
I add some new records to my people table over time, but eventually I want to merge the records from my backup table into people. Unfortunately I cannot simply DROP my table as my new records will be lost!
So I want to update the records in my people table using the records from people_backup, based on their primary key id and I have found 2 ways to do this:
MERGE the tables together
use some sort of fancy correlated update
Great! However, both of these methods use SET and make me specify what columns I want to update. Unfortunately I am lazy and the structure of people may change over time and while my CTAS statement doesn't need to be updated, my update/merge script will need changes, which feels like unnecessary work for me.
Is there a way merge entire rows without having to specify columns? I see here that not specifying columns during an INSERT will direct SQL to insert values by order, can the same methodology be applied here, is this safe?
NB: The structure of the table will not change between backups
Given that your table is small, you could simply
DELETE FROM table t
WHERE EXISTS( SELECT 1
FROM backup b
WHERE t.key = b.key );
INSERT INTO table
SELECT *
FROM backup;
That is slow and not particularly elegant (particularly if most of the data from the backup hasn't changed) but assuming the columns in the two tables match, it does allow you to not list out the columns. Personally, I'd much prefer writing out the column names (presumably those don't change all that often) so that I could do an update.

Losing data during joins in Access SQL

I have two tables, with a many to one relationship, and I am using a left join to get all the data from the many table and merge it with the data from the one table.
My first table looks like:
create table tasks (date text(6),task text(20),completed text(1))
Second table:
create table completer (data text(6),name text(20))
Keep in mind that date in the completer table is a primary key so only one name is associated with each date.
I can write a query that joins these tables and creates the correct structure:
select tasks.task,completer.name,tasks.completed from tasks left join completer on tasks.date=completer.date;
The problem with my query is my binary "completed" variable that is either 0, or 1 is always 0 after the join, no matter what value it is in the original table.
Why am I losing the data associated with the completed variable? I've tried using Access's yes/no variable instead, but that has the same problem with losing information during the join.
Thanks

How to update multiple matching records with data from another table

Working with DB2 but guess this applies to SQL in general.
I have two tables; Table1 contains data where the Fix column could be same in multiple rows. Table2 has unique rows and has data I want to add to columns in the first table if one or more matches between the Fix column in Table1 and the Title column in Table2 are found.
I'm getting an issue in that the SQL is returning an error saying: "The same row of target table "xxxxxxx" was identified more than once for an update, delete or insert operation of the MERGE statement.."
Now that is expected ie I know there are multiple rows in the target table that match the criteria and need to have the data from the source table applied to them.
I'm using MERGE but is that just not going to be possible? Been looking at GROUP BY too but can't get it to work.
If I was doing this in another language I'd go through the source table, build a collection of matching records from the source then iterate through the collection updating that with the source data that needed adding. Thinking there is a more efficient way in SQL though?
This code is completely wrong (and returns the error above) but adding it here to help any good person who wants to lend a hand :-)
CREATE PROCEDURE Update_RawData_With_xKey_Data ()
P1: BEGIN
MERGE INTO table1 AS T
USING table2 AS S
ON (T.FIX = S.TITLE)
WHEN MATCHED THEN
UPDATE SET
T.Rating = S.Rating,
T.GSDS = S.GSDS_Date,
ELSE IGNORE ;
END P1

How to only insert unique data into an access database

I have an access database that I need to update only if my information is unique. Is there a simple sql statement to accomplish this? Will 'insert ignore' work with access?
Example: I have the info stored in an array ('bob','34','hair'). If my database contains a record that matches on those three columns I would not want it to be inserted. If it was found to be unique I would like it to be inserted.
I am writing this in cold fusion but just cant seem to get the sql right.
Before doing an insert, do a select for those values. If you don't get a record back then you know it is safe to insert. Just use two separate queries, one for the check, and if no record found, then the insert.
A unique index is always a good idea if a field or set of fields should be unique. If you have a unique index in Access on the three fields, an insert will fail.
It is possible is to create a single query that only inserts a record where a matched record is not found, for example:
INSERT INTO Shows (ForeName,Reviews,Musical)
SELECT "bob" As ForeName,"34" As Reviews,"hair" As Musical
FROM (SELECT Count(*) As ExistsCount
FROM Shows
WHERE ForeName = "bob",Reviews = "34",Musical = "hair") AS e
WHERE e.ExistsCount=0