SQL Server : Insert into Multiple Tables with Foreign Keys - sql

I'm working on a project tracking grocery expenses. I have the following tables with predefined values already inserted:
Store (where we bought the food)
Shopper (me or my wife)
Category (of food)
I also have tables that are awaiting input.
They are:
Receipt (one shopping trip with multiple food items)
Food (each food item)
FoodReceipt (bridge table between Receipt and Food)
I have my constraints set up the way I need them, but I am at a bit of a loss when it comes to writing an INSERT statement that would allow me to insert a new record that references values in the other tables. Any thoughts would be greatly appreciated.
Thanks!

SCOPE_IDENTITY will give you the single value of the last identity. While it may well work in this case, that isn't necessarily the best approach in the general case when you want to insert in sets.
I'd consider using the OUTPUT clause to output the inserted items ID into a temp table, then you can join them back to the subsequent inserts.
`INSERT INTO... OUTPUT INSERTED.ID INTO tempIDs
INSERT INTO other_table inner join tempIDs ...`
Wrap it up in a SP.
https://learn.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql?view=sql-server-2017

Using the final three tables as an example, insert into the reciept table and use the ScopeIdentity() function to get the id (you have to use an identity column as the primary key). Repeat the following for each food item - insert into the food table, use ScopeIdentity to get the primary key and then insert a row into FoodReceipt the saved value for the receipt and the saved value for the current food row.

Related

one-to-one tables relationship, linked by the autonumber in the main table

I have a main table that contain the customers details, I built another table that contain for example a yes/no fields about if the customer paid his taxes, the two tables is linked with autonumber from the main table.
I want always to keep them both with the same amount of records (that means every customer has a record in the second table even if the second table has empty record with data only in the primary key field)
I need that cause with missing records I cannot run update query to auto fill the second table and i got an error of validation rule violation.
I use this sql:
update clients LEFT JOIN MonthlyTbl ON clients.SerialNo = MonthlyTbl.serialno
set sReport04='ready';
I have almost 700 records in the main table and only 80 records in the second, and when I run the sql it updates only 80!!!!
Thanks for Help
Please use below query,
update clients set sReport04='ready' where SerialNo in
(select serialno from MonthlyTbl);
here is the right answer
first run the sql:
INSERT INTO monthlytbl ( serialno )
SELECT clients.serialno FROM clients
WHERE (((clients.[serialno]) Not In (select serialno from monthlytbl)));
and then:
select sreport04 from monthlytbl
set sReport04='ready';

Moving specific data from one database to another

This is for SQL Server. I have tables Product (product_id pk) and Customers (cust_id pk). And a few other tables that have the above as foreign key.
I need to come up with a good set of INSERT statements that can move rows from the tables above, for a specific Product from one database to another. Is there a good tool that can do this?
The twist is also that the different databases have different ids for products and customers - so inserts should first look up the ids based on something else like product name and customer name (assuming there are no duplicates).
If the databases are within the same server, you may use the following assuming they have the same table structure
USE [TESTDB]
SELECT *
INTO #values
FROM producttbl
USE [OTHERDB]
INSERT INTO tbl_product
SELECT *
FROM #values
The twist is also that the different databases have different ids for
products and customers - so inserts should first look up the ids based
on something else like product name and customer name (assuming there
are no duplicates).
For this, you have to create an SQL statement with conditions to lookup for those specific records

SQL: Inserting into a (dynamic) lookup table

Most articles about lookup tables deal with its creation, initial population and use (for looking up: id-->value).
My question is about dynamic updating (inserting new values) of the lookup table, as new data is stored in data tables.
For example, we have a table of persons, and one attribute (column) of it is city of residency. Many persons would have the same value, so it makes sense to use a lookup table for it. As the list of cities that would appear is not known beforehand, the lookup table is initially empty.
To clarify, the value(s) of city is/are:
not know beforehand (we don't know what customer might contact us tomorrow)
there is no "list of all possible cities" (real life cities come and go, get renamed etc)
many persons will share the same value
initially, there will be a few different values (up to 10), later more (but not very much, a few hundred)
Also, the expected number of person objects will be thousands if not millions.
So the basic algorithm is (pseudocode):
procedure insertPerson(name,age,city)
{
cityId := lookup(city);
if cityId == null
cityId := insertIntoLookupTableAndReturnId(city);
INSERT INTO person_table VALUES (name,age,cityId);
}
What is a good lookup table organization for this problem? What exact code to use?
The goal is high performance of person insertion (whether the city is already in the lookup table or not).
General answers are welcome and Oracle 11g would be great.
Note: This is about an OLTP scenario. New persons are inserted in real time. There is no known list of persons that can be used for initialization of the lookup table.
Your basic approach appears to be OK except for one small change I would do: The function lookup(city) will search for the city and return the ID and, if the city is not found, will insert a new record and return its ID. This way, you are further encapsulating the management of the lookup table (cities). As such, your code would become:
procedure insertPerson(name,age,city)
{
INSERT INTO person_table VALUES (name,age,lookup(city));
}
One additional thing you may consider is to create a VIEW that would be used to query for persons' information, including the name of the city.
After some testing, the best performance (least block accesses) I could find was with an index organized table as the lookup table and the below SQL for inserting data.
create table citylookup (key number primary key, city varchar2(100)) organization index;
create unique index cltx1 on citylookup(city);
create sequence lookupkeys;
create sequence datakeys;
create table data (x number primary key, k number references citylookup(key) not null);
-- "Rome" is the city we try to insert
insert all
when oldkey is null then -- if the city is not in the lookup yet
into citylookup values (lookupkeys.nextval, 'Rome') -- then insert it
-- finally, insert the data row with the correct lookup key
when 1=1 then into data values (datakeys.nextval,nvl(oldkey, lookupkeys.nextval))
select (select key from citylookup where city='Rome') as oldkey from dual;
Result: 6+2 blocks for city-exists case, 10+2 for city-doesn't-exists yet (as reported by SQL*Plus with set autotrace on: first value is db block gets, the second consistent gets).
Alternatively, as suggested by Dudu Markovitz, the lookup table could cached in the application and in the hit case just perform an simple INSERT into the DATA table, which then costs only 6+1 block accesses (for the above test case). Here the problem is keeping the cached lookup table in sync with the database and possible other instances of the server application.
PS: The above INSERT ALL command "wastes" a sequence value from the lookupkeys sequence on each run, even if no new city is inserted into the lookup table. It is an additional exercise to solve that.

How do I get an unique ID per transaction which has multiple insertions

I had two text boxes in frond end which is productname and No.of.batches...For example I selected a product 'X' and No.of batches as 10..It will get 10 rows and user will insert the data when user clicks submit it will reflect in database too...My requirement is generate an ID automatically PER transaction...I had to get an unique ID for the whole operation...what should i do to get that?
I assume you are talking about financial as opposed to database transactions but the same applies to both.
Per prdb's ansswer above, create a table for storing the transaction header information (don't call it transaction since that is a reserved word). Call it something else.
Add appropriate foreign keys referencin that table.
Then your insert looks like this:
insert into the transaction header table and use OUTPUT or another select to get the id out
Insert into the other tables adding the transaction header id as a foreign key as needed.
Again, that's pretty standard with financial transactions. For db transactions, the same approach could be used.
Create a new table called transactions with auto generated column.
Create table transactions
(
transaction_id int identity(1,1) Primary key,
product_name varchar(50),
No_of_batches int
)
Whenever there is a new transaction then first add a entry in transaction table and refer the auto generated value(transaction_id) in your target table for all the X records

Is it possible to insert data into table using two select statements in one query?

I am working with databases in which I have 3 tables one is skill table the other one is experience and the third one is Experience_skill table in this table I have foreign keys now the question is both foreign keys are primary keys as well. Let say I am storing data into skill table as well as in experience table how can I insert the the both keys data there in Experience_skill table. I have tried following queries.
insert into Experience_skill(eid, Skill_Id)
select eid
from Experience
where eid=2
union
select Skill_Id
from Skills
where Skill_Id=2
error I get:
The select list for the INSERT statement contains fewer items than the insert list. The number of SELECT values must match the number of INSERT columns.
Than i tried this one.
insert into Experience_skill(eid)select eid from Experience where eid=2
it gives me this error:
Cannot insert the value NULL into column 'Skill_Id', table 'resume.dbo.Experience_skill'; column does not allow nulls. INSERT fails.
Please help me out
here are the snapshots of the table first snap shot is of skill table
the second one is experience table
And this one is EXperience_skill table where i have my foreign keys
When using INSERT INTO, you need to supply ALL of the columns in the destination table (that do not allow NULLs) in each ROW of the SELECT.