How to sync to tables in MS Access? - database

I have two tables in MS Access: table1 and table2. In table1 I have fields: ID, name (text), short_name (text), description (text), use_in_table2 (checkbox). In table2 I have fields: ID, name (text), max (num), min (unm) and others. I want to copy object from table1 to table2 with use_in_table2 == True. Also if I reset checkbox use_in_table2 in table1, I will delete corresponding object from table2. I use same ID for same objects in both tables. I use simple python script for my task. How can I solve this problem in MS Access?

The short answer is don't do it this way. Don't Repeat Yourself(DRY). In most cases there is no need for Table 2. Just create Table 2 every time you need it with a select query. You can use the Query Designer to help you write the sql. You can even hit make table and create a table rather than a query but for most purposes they work the same.
'select query
SELECT Table1.Table1ID, Table1.Month, Table1.X, Table1.Y, Table1.use_in_table2
FROM Table1
WHERE (((Table1.use_in_table2)=True));
'make table query
SELECT Table1.Table1ID, Table1.Month, Table1.X, Table1.Y, Table1.use_in_table2 INTO Table2
FROM Table1
WHERE (((Table1.use_in_table2)=True));
To answer the question posed. Note the Delete and Update Tabs. After Making Table2 you must run two queries rather than just 1. A delete Query for records where use_in_table2 is false and an update query where use_in_table2 is true. I ran out of time; look those up

Related

Update Query with Order by while preventing two users updating the same row

I have a SQL Server table with an expirydate column, I want to update rows on this table with the nearest expirydate, running two queries (select then update) won't work because two users may update the same row at the same time, so it has be one query.
The following query:
Update Top(5) table1
Set col1 = 1
Output deleted.* Into table2
This query runs fine but it doesn't sort by expirydate
This query:
WITH q AS
(
SELECT TOP 5 *
FROM table1
ORDER BY expirydate
)
UPDATE table1
SET col1 = 1
OUTPUT deleted.* INTO table2
WHERE table1.id IN (SELECT id FROM q)
It works but again I run the risk of two users updating the same row at the same time
What options do I have to make this work?
Thanks for the help
In these types of scenarios if you want a more optimistic concurrency approach, you need to include either an Order By AND / OR a Where clause to filter out the rows.
In application design it is common to use SELECT TOP (#count) FROM... style queries to fill the interface, however to execute DELETE or UPDATE statements you would use the primary key to specifically identify the rows to modify.
As long as you are not executing delete, then you could use a timestamp or other date based descriminator column to ensure that your updates only affect the rows that haven't been changed since the last select.
So you could query the current time as part of the select query:
SELECT TOP 5 *, SYSDATETIMEOFFSET() as [Selected]
FROM table1
ORDER BY expirydate
or query for the timestamp first, and add a created column to the table to track new records so you do not include them in deletes, either way you need to ensure that the query to select the rows will always return the same records, even if I run it tomorrow, which means you will need to ensure that no one can modify the expirydate column, if that could be modified, then you can't use it as your primary sort or filter key.
DECLARE #selectedTimestamp DateTimeOffset = (SELECT SYSDatetimeoffset())
SELECT TOP 5 *, SYSDATETIMEOFFSET() as [Selected]
FROM table1
WHERE CREATED < #selectedTimestamp
ORDER BY expirydate
Then in your update, make sure you only update the rows if they have not changed since the time that we selected them, this will either require you to have setup a standard audit trigger on the table to keep created and modified columns up to date, or for you to manage it manually in your update statement:
WITH q AS
(
SELECT TOP 5 *
FROM table1
WHERE CREATED < #selectedTimestamp
ORDER BY expirydate
)
UPDATE table1
SET col1 = 1, MODIFIED = SYSDatetimeoffset()
OUTPUT deleted.* INTO table2
WHERE table1.id IN (SELECT id FROM q)
AND MODIFIED < #selectedTimestamp
In this way we are effectively ignoring our change if another user has already updated records that were in the same or similar initial selection range.
Ultimately you could combine my initial advice to UPDATE based on the primary key AND the modified dates if you are genuinely concerned about the rows being updated twice.
If you need a more pessimistic approach, you could lock the rows with a specific user based flag so that other users cannot even select those rows, but that requires a much more detailed explanation.

TSQL - Loop over column to query other table

I'm stuck with the following task:
via Excel the user types in an ID then clicks a button (macro) to trigger SP or function
this ID usually "returns" more than one row
from this result I need the values of a single column (LookupNumber) in order to use those values to query or join another view. Looping required?
as a result I want to join the initial ID request table with the result of the other queried table.
In below image, the first table holds the ID the user wants to search.
The second table should be queried by the LookupNumber values that were retrieved from table A.
The third table shows the desired output:
The problem I have is how do I loop (if needed) through the LookupNumber once the search ID has been passed? I don't know what methods I should use for this task.
Because sqlfiddle doesn't seem to work, I put the tables from above screenshot in this link
Hopefully you can give me some ideas how to solve this.
Something like this should work:
select t1.*, t2.*
from table2 t2
inner join (
select ID, Subject, Project, LookupNumber
from table1
where id = <entered id>
) t1 on t1.LookupNumber = t2.LookupNumber

Need help on a sql query to get data from multiple tables

I have a couple of tables that have data in them that I am looking to get information from. Here is the rundown....In table 1 I have bunch of columns that I am pulling data from, one of the columns is a user ID (which is a number)that was the last userID to modify a record. In table 2 I want to pull in the name of that user based on the ID that is pulled from the other table (this table has both the userID and the username).
so my final query would have the columns in table 1 as well as the username from table 2 to show that was the user to last edit the record. I assume this has to be done in a nested select statement but for the life of me I cannot come up with the correct syntax.
Can anyone help me out?
Thanks
Jeff
Yes, you need a very basic join that link both tables together.
Select t1.UserID,
t2.UserName
FROM table1 t1 INNER JOIN
table2 t2 ON t1.userid=t2.userid
select t1.*, t2.{username} from table1 as t1
join table2 as t2 on t1.{userId}=t2.{userid};
change {username} with the actual column name of user
similarly {userId} with appropriate column name in tables.
Hope it helps you.
this is standard inner join query, to learn more consider reading: http://www.w3schools.com/sql/

Unique entries over to tables in database

I have a problem where I need to check that two columns in each table in a database are unique.
We have the database with barcode entries called uid and rid.
Table 1: T1.uid
And
Table 2: T2.rid
No barcodes in the two table columns must be the same.
How can we ensure that.
If a insertion of a barcode into table T1.uid matches an entry in
T2.rid we want to throw an error.
The tables are cleaned up and is in a consistent state where the entries in
T1.uid and T2.rid are unique over both table columns.
It is not possible to insert NULL values in the tables respective uid and tid column(T1.uid and T2.rid)
It is not possible to create a new table for all barcodes.
Because we don't have full control of the database server.
EDIT 19-02-2015
This solution cannot work for us, because we cannot make a new table
to keep track of the unique names(see table illustration).
We want to have a constraint over two columns in different tables without changing the schema.
Per the illustration we want to make it impossible for john to exist in
T2 because he already exists in table T1. So an error must be "thrown"
when we try to insert John in T2.Name.
The reason is that we have different suppliers that inserts into these tables
in different ways, if we change the schema layout, all suppliers would
need to change their database queries. The total work is just to much,
if we force every suppplier to make changes.
So we need something unobtrusive, that doesnt require the suppliers to change
their code.
A example could be that T1.Name is unique and do not accept NULL values.
If we try insert an existing name, like "Alan", then an exception will occur
because the column has unique values.
But we want to check for uniqueness in T2.Name at the same time.
The new inserted value should be unique over the two tables.
Maybe something like this:
SELECT uid FROM Table1
Where Exists (
SELECT rid FROM Table2
WHERE Table1.uid = rid )
This will show all rows from Table1 where their column uid has an equivalent in column rid of Table2.
The condition before the insertion happens could look like below. #Idis the id you need to insert the data for.
DECLARE #allowed INT;
SELECT #allowed = COUNT(*)
FROM
(
SELECT T1.uid FROM T1 WHERE T1.uid = #Id
UNION ALL
SELECT T2.rid FROM T2 WHERE T2.rid = #id
)
WHERE
#id IS NOT NULL;
IF #allowed = 0
BEGIN
---- insert allowed
SELECT 0;
END
Thanks to all who answered.
I have solved the problem. A trigger is added to the database
everytime an insert or update procedure is executed, we catch it
check that the value(s) to be inserted doens't exist in the columns of the two
tables. if that check is succesfull we exceute the original query.
Otherwise we rollback the query.
http://www.codeproject.com/Articles/25600/Triggers-SQL-Server
Instead Of Triggers

Select rows based on time or all rows if the table is empty

I have 2 tables. One is a production table and the other is a daily reporting table. The daily reporting table is emptied each day. The daily reporting table is a subset of the production table. I want to update the daily table with all new rows from production table. I thought about using a where clause;
SELECT ftime,
fdate,
fdata,
fdata2
INTO table2
FROM table1
WHERE ftime > table2.ftime
I am not having much luck. I am new to SQL and I am just not sure how to go about this, and can't seem to find anything on the net for this specific issue.
This will eventually go into a stored procedure when I get it working.
Any tips, hints, would be greatly appreciated.
SELECT ftime,
fdate,
fdata,
fdata2
INTO table2
FROM table1
WHERE ftime > (select MAX(ftime) from table2)
OR NOT EXISTS (select * FROM table2);
If table2 is empty (such as if you have just done your daily purge), all of table1 will get pulled into table2.
Otherwise it will only insert the new records from table1 with ftime later than what exists in table2.
Make sure you have an index on table2.ftime

Resources