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

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

Related

Create SQL Number that can be changed to specify the route order of deliveries

I'm using SQL server and linking to an Access Front-End. The project is for a delivery of goods. The user will add Sales and then check the best route using Google Maps (I don't have permission to use API keys). In any case, they will add an order and then decide which orders placed will be delivered 1st, 2nd, 3rd, etc. They always leave from HQ so the route order is zero. I need to make sure there is no overlap of numbers so I can order by that number and total the distance that will be travelled based on that route.
Two users could be adding a record at the same time for the Day and Vehicle (I use a table that stores every day and every vehicle with an ID. So Van 1 - 01/01/2023 is ID:1. Van 2 - 01/01/2023 ID:2 etc. I use an Orders table in it's in here that I need to store the Route Order Sequence. the users will specify a better route by altering the selected record Up or Down in the list, altering the sequence.
So far I'm using VBA in Access to generate the numbers, but if I have two users attempting to add orders to the Same Vehicle/Date record, the VBA is failing. I don't want to prevent to users adding to the same Van/Date as this happens a lot. Plus I'm not convinced that even if I did do that, that my VBA is robust enough to provide the correct sequence. Ideally I want SQL to handle the number, not VBA.
I have worked with a system that used a primary key in one table to generate a unique ID across systems. It leveraged the following table structure.
CREATE TABLE [dbo].[OrderNumber]
( [OrderId] [int] NOT NULL,
[Assigned] [datetime] NOT NULL CONSTRAINT DF_OrderNumber_OrderId DEFAULT (GETDATE()),
CONSTRAINT [PK_OrderNumber] PRIMARY KEY CLUSTERED ([OrderId] ASC)
) ON [PRIMARY];
You will need to make sure that there is an initial value populated:
INSERT dbo.OrderNumber (OrderId) VALUES (0);
From there you will need to use a stored procedure containing a transaction to make sure that the value is unique. You can use the OUTPUT clause to capture the inserted value.
ALTER PROCEDURE
dbo.GetOrderNumber
AS
BEGIN
BEGIN TRY
BEGIN TRANSACTION GetOrderNumbers;
DECLARE #Temp TABLE (OrderId INT);
INSERT INTO OrderNumber
( OrderId)
OUTPUT
inserted.OrderId
INTO
#Temp
SELECT
MAX(OrderId) + 1
FROM
OrderNumber;
COMMIT TRANSACTION GetOrderNumbers;
SELECT TOP 1 OrderId FROM #Temp;
END TRY
BEGIN CATCH
IF (##TRANCOUNT = 0)
RETURN;
ROLLBACK TRANSACTION GetOrderNumbers;
THROW;
END CATCH;
END
You will need to add error handling in case there is an error retrieving the data.

How would I write a SQL Function to Update Store Averages upon INSERT to transactions table?

I am attempting to create a SQL trigger function that should UPDATE a secondary table when data is INSERTED into the original table. The update would be based on the amount and store_id columns.
I have the following table to store every transaction that has happened at both stores being represented.
CREATE TABLE transactions(
payment_id INT NOT NULL PRIMARY KEY,
payment_date TIMESTAMP NOT NULL,
store_id INT NOT NULL,
amount FLOAT NOT NULL
);
When an insert is completed, I want my store_averages table to have the averages that are represented updated, as well. This table was created like so: (note: there are only 2 stores being tracked in these tables)
CREATE TABLE store_averages AS
SELECT transactions.store_id, avg(transactions.amount)
FROM transactions
WHERE transactions.store_id=1
GROUP BY transactions.store_id;
INSERT INTO store_averages
SELECT transactions.store_id, avg(transactions.amount)
FROM transactions
WHERE transactions.store_id=2
GROUP BY transactions.store_id;
In my testing, I have been able to update the values from a trigger for one store, but not both. How would I do this?
I doubt you want to keep inserting values with no other information to your store_averages table, as there's nothing present to indicate which is most current. If the intent is to have a table that contains only the most current store averages following each transaction, I'd ask a few more questions that may be fit for purpose - such as frequency of updates occurring, and whether this needs to be real-time updates or perhaps just maintained hourly / daily.
My initial thought would be to create a view or materialized view for this information ...

SQL Server : Insert into Multiple Tables with Foreign Keys

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.

What kind of approach is this in SQL, it actually exists? Is it viable/good pratice?

One of our teachers gave us the following challenge:
"Make a Database schema with the following principle:
you can't change any values on any table, only add new ones."
I came with the following schema:
CREATE TABLE TRANSACTIONS(ID PRIMARY KEY, TRANSACTION_TYPE_FK, DATE);
CREATE TABLE TRANSACTION_TYPE(ID PRIMARY KEY, NAME);
CREATE TABLE PRODUCTS_TRANSACTIONS(ID_PROD_FK, ID_TRANS_FK, MONEY, QTY);
CREATE TABLE PRODUCTS(ID PRIMARY KEY, NAME, PRICE_FK );
CREATE TABLE PRICES(ID PRIMARY KEY, DATE, DETAILS);
It's just a proof of concept. Basically everything is based on transactions.
Transactions can be Entry, Exit and Move Products and In & Out Money.
I can control my quantities and cash based on transactions.
The PRODUCTS_TRANSACTIONS "MONEY" field is used if a transaction involves money only or there are "discounts" or "taxes" on the transaction.
The Products Table has a "child" table called "prices", it storages all the price changes , the "details" field is for annotations like "Cost Price" etc.
I made it very quick, I am sorry for any inconsistency.
I liked this kind of approach, I am kinda of a newbie with SQL so I really wanted to know if this approach has a name and if it is viable perfomance-wise or a good pratice.
My idea is making a View and "update" it whenever a new transaction is made, since nothing needs to be "updated" I only need to add new rows to the View.
I am currently very sick, so I can't go to college to remedy my doubts.
Thanks in advance for any help
Let's take only one table TRANSACTION_TYPE(ID PRIMARY KEY, NAME) for example:
Now if you want to restrict update on the table, you can achieve that with following queries:
GRANT SELECT,INSERT,DELETE ON TRANSACTION_TYPE TO Username;
OR
Deny UPDATE ON TRANSACTION_TYPE TO Username;
Now to maintain history of insertion and deletion,you can store in another table by creating trigger on TRANSACTION_TYPE as follows:
CREATE or REPLACE TRIGGER my_trigger // name of trigger
AFTER INSERT OR DELETE
ON TRANSACTION_TYPE
FOR EACH ROW
BEGIN
IF INSERTING THEN
INSERT INTO TRANSACTION_INSERT_HISTORY(ID,NAME) //table that maintain history of insertion
VALUES(:new.ID,:new.NAME);
ELSIF DELETING THEN
INSERT INTO TRANSACTION_DELETE_HISTORY(ID,NAME) //table that maintain history of deleted records
VALUES(:old.ID,:old.NAME);
END IF;
END;
/
Before creating this trigger, you first have to create two tables:
TRANSACTION_INSERT_HISTORY(ID,NAME) and
TRANSACTION_DELETE_HISTORY(ID,NAME)
I have created two different tables for insertion and deletion for simplicity.
You can do it with one table too.
Hope it helps.
The table that holds the information, you could give permissions only to insert and select to the table, preventing update.
https://www.mssqltips.com/sqlservertip/1138/giving-and-removing-permissions-in-sql-server/
GRANT INSERT, SELECT ON TableX TO UserY
In a production system, you'd probably design this using a VIEW for selecting the data from the table (to only get the most recent revision of the audit data). With perhaps another VIEW that would allow you to see all the audit history. You'd probably also make use of a Stored Procedure for inserting the data and ensuring the data was being maintained in the audit history way you suggest.

Auto Increment feature of SQL Server

I have created a table named as ABC. It has three columns which are as follows:-
The column number_pk (int) is the primary key of my table in which I have made the auto increment feature on for that column.
Now I have deleted two rows from that table say Number_pk= 5 and Number_pk =6.
The table which I get now is like this:-
Now if I again enter two new rows in this table with the same value I get the two new Number_pk starting from 7 and 8 i.e,
My question is that what is the logic behind this since I have deleted the two rows from the table. I know that a simple answer is because I have set the auto increment on for the primary key of my table. But I want to know is there any way that I can insert the two new entries starting from the last Number_pk without changing the design of my table?
And how the SQL Server manage this record since I have deleted the rows from the database??
The logic is guaranteeing that the generated numbers are unique. An ID field does not neccessarily have to have a meaning, but rather is most often used to identify a unique record, thus making it easier to perform operations on it.
If your database is designed properly, the deleted ID numbers would not have been possible to delete if they were referenced by any other tables in a foreign key relationship, thus preventing records from being orphaned in that way.
If you absolutely want to have entries sequences, you could consider issuing a RESEED, but as suggested, it would not really give you much advantages.
The identity record is "managed" because SQL Server will keep track of which numbers have been issued, regardless of whether they are still present or not.
Should you ever want to delete all records from a table, there are two ways to do so (provided no foreign key relatsons exist):
DELETE FROM Table
DELETE just removes the records, but the next INSERTED value will continue where the ID numbering left of.
TRUNCATE TABLE
TRUNCATE will actually RESEED the table, thus guaranteeing it starts again at the value you originally specified (most likely 1).
Although you should not do this until their is a specific requirement.
1.) Get the max id:
Declare #id int
Select #id = Max(Number_pk) From ABC
SET #id = #id + 1;
2.) And reset the Identity Column:
DBCC CHECKIDENT('ABC', RESEED, #id)
DBCC CHECKIDENT (Transact-SQL)