I have two tables, Price List and Price Code:
CREATE TABLE PriceLists
(
PriceListID INT IDENTITY(1,1) NOT NULL,
Reference NVARCHAR(50) NOT NULL,
Description NVARCHAR(255) NOT NULL
)
Each Price List had lots of price codes:
CREATE TABLE PriceCodes
(
PriceCodeID INT IDENTITY(1,1) NOT NULL,
PriceListID INT NOT NULL
PriceCodeName NVARCHAR(50) NOT NULL
)
Basically what I need is a stored procedure; when a new price list is entered, that stored procedure is going to add same number of price codes to the PriceCodes table with new PriceListID.
For example:
If a new row is inserted into the PriceList table with PriceListID = 1 and Reference = 2017, then the stored procedure should insert these rows into the PriceCode table:
PriceCodeID PriceListID PriceCodeName
------------------------------------------
1 1 CodeA
2 1 CodeB
3 1 CodeC
And if we have this data in the PriceList table :
PriceListID Reference
------------------------
1 2017
1 2018
then the PriceCodse table should be like this:
PriceCodeID PriceListID PriceCodeName
------------------------------------------
1 1 CodeA
2 1 CodeB
3 1 CodeC
4 2 CodeA
5 2 CodeB
6 2 CodeC
You could easily package this up into an AFTER INSERT trigger, and even get rid of that ugly cursor - try this:
CREATE TRIGGER trg_InsertPriceCodes
ON dbo.PriceLists
AFTER INSERT
AS
BEGIN
INSERT INTO dbo.PriceCodes (PriceListID, PriceCodeName)
SELECT i.PriceListID, VAL.Name
FROM Inserted i
CROSS APPLY (VALUES ('CodeA'), ('CodeB'), ('CodeC')) AS VAL(Name)
END
So now, any time you insert a row into PriceLists, the trigger will take care of adding three rows with values CodeA, CodeB, and CodeC for PriceCodeName into the PriceCodes table. No stored procedure and no RBAR (row-by-agonizing-row) trigger necessary.....
I wrote this code and it seems working, just need few adjustments.
SET NOCOUNT ON;
DECLARE #priceCodeName VARCHAR(50), #PriceListID INT, #PriceGroup VARCHAR(20);
DECLARE priceCode_cursor CURSOR FOR
SELECT PriceCodeName ,PriceListID ,PriceGroup
FROM PriceCodes2
ORDER BY PriceCodeName;
OPEN priceCode_cursor
FETCH NEXT FROM priceCode_cursor
INTO #priceCodeName, #PriceListID, #PriceGroup
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO [dbo].[PriceCodes2]
([PriceCodeName]
,[PriceListID]
,[PriceGroup])
VALUES
(#priceCodeName,#PriceListID,#PriceGroup)
FETCH NEXT FROM priceCode_cursor
INTO #priceCodeName, #PriceListID, #PriceGroup
END
CLOSE priceCode_cursor;
DEALLOCATE priceCode_cursor;
Related
I am trying to write a stored procedure that would increment one of the column in the table by 1, everytime either of the country code (AXX,XPP,CGG) is given as user input, depending on the already existing country code value
ID CountryCode
1 AXX
2 AXX
1 XPP
3 AXX
4 AXX
2 XPP
My code below fetches a value that reads the ID like
ID
1
2
3
4
...
...
Create procedure [dbo].[sp_Incremental]
#code varchar(50)
as
begin
declare #IDbigint
set #ID= 1 ;
begin try
Select #ID=count(ID)+1 from [Incremental_tbl]
Begin
Insert into [Incremental_tbl] values (#ID,#code)
End
end
go
You can use this SP :
CREATE PROCEDURE p_Incremental #code VARCHAR(50)
AS
SET NOCOUNT ON;
INSERT INTO Incremental_tbl (ID, code)
SELECT COALESCE(MAX(ID), 0) + 1, #code
FROM Incremental_tbl
GROUP BY #code;
GO
But, do not forget that, in concurrency acesses, same values can occur for the ID !
I have two tables Product and Purchase:
Product table:
ProductID = 1
PName = tv
StockQty = 10
Purchase table:
PurchaseID = 1
PID = 1
PurchaseQty = 5
Product ID is a foreign key in Purchase table. I am trying to write a stored procedure so that whenever Purchase Quantity is added in Purchase table, the main table Product should also be changed.
For example: I add purchase quantity 5. When I refresh the Product table, it should display 15. With my current stored procedure, it is updating all products and increases StockQty by 5 - instead it should do this to only the product id I chose. Please advise.
Below is my stored procedure:
CREATE PROCEDURE insertpurchase
#PID int,
#PurchaseQty int,
#StockQty int
AS
INSERT INTO [dbo].[Purchase] (PID, PurchaseQty)
VALUES (#PID, #PurchaseQty)
BEGIN
UPDATE [dbo].[Product]
SET Product.StockQty = Product.StockQty + Purchase.PurchaseQty
FROM Purchase
END
Can somebody guide what is wrong with my query?
You need to add where clause while updating.
'CREATE PROCEDURE
insertpurchase
#PID int ,
#PurchaseQty int,
#StockQty int
AS
INSERT INTO [dbo].[Purchase] (PID ,PurchaseQty ) VALUES (#PID ,#PurchaseQty )
BEGIN
UPDATE [dbo].[Product]
SET Product.StockQty = Product.StockQty + #PurchaseQty
WHERE ProductID = #PID
END '
It’s true that the stored procedure needs the filter for the ProductID on the update statement. however, to make sure both update and insert are executed properly, I made some adjustment to the code with the following
1.) I removed #StockQty because in that scenario it seems that the stored procedure only require the id of puchases item and purchase quantity
2.) I add the Transaction to make sure that both insert and update are executed properly, without it, it is possible to insert but does not update.
CREATE PROCEDURE insertpurchase
#PID int,
#PurchaseQty int
AS
BEGIN TRANSACTION
INSERT INTO [dbo].[Purchase] (PID, PurchaseQty)
VALUES (#PID, #PurchaseQty)
BEGIN
UPDATE [dbo].[Product]
SET Product.StockQty = Product.StockQty + #PurchaseQty
FROM Purchase
WHERE ProductID = #PID
COMMIT TRANSACTION
END
create procedure SP_insert_test #name varchar(20), #emailid varchar(20), #trainer_name varchar(50), #training_date varchar(50), #training_time varchar(50), #gymname varchar(50) , #success int out as
begin
if(
select
count(id)
from
Add_Booking_Fitness_Training
where
training_time = #training_time) > 11 print N'Number of Booking Is Complete for this time and date plz book other time';
else
insert into
Add_Booking_Fitness_Training(memeber_name, member_emailid, trainer_name, training_date, training_time, gymname)
values
(
#name,
#emailid,
#trainer_name,
#training_date,
#training_time,
#gymname
)
SELECT
SCOPE_IDENTITY()
set
#success = 1;
end
begin
set
#success = 0;
end
i have an table in which i want to insert data on give time only 12 member can insert at that time after that they get message list is full plz change the time for inserting i have create procedure its working when its reach number of 12 than its show me message but when i change the time its also show me the same message and not insert any data into database
like 26/04/2018,'6:00' i want to insert this value only 12 time after 12 this show me a message about the limit of number is reach plz change (time)
Create table Add_Booking_Fitness_Training ( id int identity primary key,
memeber_name varchar(20),
member_emailid varchar(20),
trainer_name varchar(50),
training_date varchar(50),
training_time varchar(50),
gymname varchar(50))
i just want to inserting a value into this table only 12 time for a give time like (6:00) if the number of inserting value reach to 12 than its show me the message number of values insert is reach to 12 please change the time.
i want input the value into table only 12 time for a give time 6:00Am when the value is insert into table 12 time than message come up for change time than insert value for change time
Honestly, I am completely guessing here, I still don't really know what you're asking.
I think the OP's statement of "i want input the value into table only 12 time for a give time 6:00Am when the value is insert into table 12 time than message come up for change time than insert value for change time." means that they only want a time to appear in the table up to 12 times. If it appears more than that, the INSERT fails.
This can be achieved with a check constraint and a scalar function. So, as a very simple example:
USE Sandbox;
GO
--Create a very simple table
CREATE TABLE SampleTable (TrainingTime datetime2(0));
GO
--Create the scalar function
CREATE FUNCTION TrainingAtTime (#TrainingTime datetime2(0))
RETURNS INT
AS BEGIN
DECLARE #Trainees int;
SELECT #Trainees = COUNT(*)
FROM SampleTable
WHERE TrainingTime = #TrainingTime;
RETURN #Trainees;
END
GO
--Add the check constraint
ALTER TABLE SampleTable ADD CONSTRAINT MaxTrainees CHECK (dbo.TrainingAtTime(TrainingTime) <= 12) ;
GO
--Insert first trainee
INSERT INTO SampleTable
VALUES ('2018-04-26T06:00:00');
--It works
SELECT TrainingTime, COUNT(*) AS Trainees
FROM SampleTable
GROUP BY TrainingTime;
GO
--insert 11 more
INSERT INTO SampleTable
VALUES ('2018-04-26T06:00:00'),
('2018-04-26T06:00:00'),
('2018-04-26T06:00:00'),
('2018-04-26T06:00:00'),
('2018-04-26T06:00:00'),
('2018-04-26T06:00:00'),
('2018-04-26T06:00:00'),
('2018-04-26T06:00:00'),
('2018-04-26T06:00:00'),
('2018-04-26T06:00:00'),
('2018-04-26T06:00:00');
--It works
SELECT TrainingTime, COUNT(*) AS Trainees
FROM SampleTable
GROUP BY TrainingTime;
GO
--Try to insert another
INSERT INTO SampleTable
VALUES ('2018-04-26T06:00:00');
--It fails
SELECT TrainingTime, COUNT(*) AS Trainees
FROM SampleTable
GROUP BY TrainingTime;
GO
--Use a different time
INSERT INTO SampleTable
VALUES ('2018-04-26T08:00:00');
--it works
SELECT TrainingTime, COUNT(*) AS Trainees
FROM SampleTable
GROUP BY TrainingTime;
GO
--Clean up
DROP TABLE SampleTable;
DROP FUNCTION TrainingAtTime;
GO
If this isn't what you're after, unfortunately I don't understand your requirements due the the language barrier (and absence of a question).
I'm creating a temp table to store data from a csv and then altering the table after to create a new column to identify each row by a unique number in ascending order.
This gets created fine, however I can't query the table using these row numbers. Seems as if it doesn't get set. On SSMS when I use the newly created column it red lines it with the error Invalid Column Name 'columnName' but I can still query the database.
declare #loopNum INT
set #loopNum = 0
CREATE TABLE #A
(
column1 BIGINT NOT NULL,
column2 BIGINT NOT NULL,
)
DECLARE #command NVARCHAR(150)
SET #command = just reads from file into temp table A. this works fine
EXEC SP_EXECUTESQL #command
ALTER TABLE #A
ADD RowNumbers INT IDENTITY(1,1)
--if i run a select * from #a, all 4 columns show perfectly
while #loopNum <= 5
begin
select * from #a where loopNum = RowNumbers -- doesn't return anything yet loop is going up one as 6 blank results are returned
set #loopNum = #loopNum + 1
end
The select statement doesn't recognise "RowNumbers" so I'm not sure if there's a problem with how I've done the alter command.
This is what I get so far.
Column 1 | Column 2 | RowNumbers
A | B | 1
C | D | 2
It just doesn't loop through it.
A couple of issues here.
One, you're going to get an empty row first always because you declared #loopNum = 0 and your WHILE loop starts at 1.
Two, you are using "loopNum" instead of your variable #loopNum in your SELECT.
Rextester: http://rextester.com/XJNML62761
I am incrementing the alphanumeric value by 1 for the productid using stored procedure. My procedure incrementing the values up to 10 records, once its reaching to 10th say for PRD0010...no more its incrementing... however, the problem is it is repeating
the same values PRD0010.. for each SP call.
What could be the cause of this?
create table tblProduct
(
id varchar(15)
)
insert into tblProduct(id)values('PRD00')
create procedure spInsertInProduct
AS
Begin
DECLARE #PId VARCHAR(15)
DECLARE #NId INT
DECLARE #COUNTER INT
SET #PId = 'PRD00'
SET #COUNTER = 0
SELECT #NId = cast(substring(MAX(id), 4, len(MAX(id))) as int)
FROM tblProduct group by left(id, 3) order by left(id, 3)
--here increse the vlaue to numeric id by 1
SET #NId = #NId + 1
--GENERATE ACTUAL APHANUMERIC ID HERE
SET #PId = #PId + cast(#NId AS VARCHAR)
INSERT INTO tblProduct(id)values (#PId)
END
Change
SELECT #NId = cast(substring(MAX(id), 4, len(MAX(id))) as int)
FROM tblProduct group by left(id, 3) order by left(id, 3)
To
SELECT TOP 1
#NId = cast(substring(id, 4, len(id)) as int)
FROM tblProduct order by LEN(id) DESC, ID DESC
You have to remember that
PRD009
is always greater than
PRD0010
or
PRD001
All in all, I think your approach is incorrect.
Your values will be
PRD00
PRD001
...
PRD009
PRD0010
PRD0011
...
PRD0099
PRD00100
This will make sorting a complete nightmare.
In addition to astander's analysis, you also have a concurrency issue.
The simple fix would be to add this at the beginning of your proc:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
And add a COMMIT at the end. Otherwise, two callers of this stored proc will get the same MAX/TOP 1 value from your table, and insert the same value.
Also, you can and should prevent these duplicates from existing by adding a key to your table, for this column. If you already have a PRIMARY KEY on this table, you can add an additional key using a UNIQUE constraint. This will prevent duplicates occurring in the future, no matter what programming errors occur. E.g.
ALTER TABLE tblProduct ADD CONSTRAINT UQ_Product_ID UNIQUE (ID)