Calling procedure from multi user - c#

I have come up with scenario and i am really struggling with it. Please help me in this. i have table below and store procedure is calling for this table on button click in c# and data source is assign to grid.
Id Product QtyReceive QtyDispatch Location
1 HP2030 20 0 A
Below is procedure which is call on click event and it just select the require quantity of product which we require from specific location.
DECLARE #Data TABLE
(
Id int identity(1,1)
, Product varchar(10)
, QtyReceive int
, QTYDispatch int
, Location varchar(10)
)
DECLARE #Qty int = 10
INSERT #Data VALUES
('HP2030', 20 ,5,'A');
WITH sumqty AS
(
SELECT *, SUM(QtyReceive -QTYDispatch) OVER (PARTITION BY Product ORDER BY Id) AS TotalQty FROM #Data
)
,takeqty AS (
SELECT *,
CASE
WHEN #Qty >= TotalQty THEN QtyReceive
ELSE #Qty - ISNULL(LAG(TotalQty) OVER (PARTITION BY Product ORDER BY Id), 0)
END AS TakeQty
FROM sumqty
)
SELECT
Product
, TotalQty
, TakeQty
, Location
FROM takeqty WHERE TakeQty > 0
ORDER BY Location;
Now there is a problem let say two user sitting at two different computer and User 1 required 10 quantity and other user required 5 quantity. They click button to get quantity at same time and save it at same time and dispatch quantity update with quantity 10 instead of 10+5=15. It happens when both user hit save at same time. No of user can be vary. Is there any solution to this problem?
I try to understand the whole scenario.

Related

sql select a default row if the result is not found

Suppose that I have table that holds some data for individuals and companies, and I want to retrieve default value if no data found for individuals or companies, for example, suppose that I have a table
CustomerAccountId CustomerAccountType DueDays IsAdjustable isDefaultForIndividual isDefaultForCompany
1 Individual 10 true false false
2 Company 20 false false false
null null 5 false true false
null null 30 true false true
I want to create a function that takes two parameters IndividualCustomerAccountId and CompanyCustomerAccountId if IndividualCustomerAccountId found in the table retrieve it, if not found retrieve the default value for individuals which is the third row in this case , the same for companies, if theCompanyCustomerAccountIdis found retrieve it, if not get the default value for the companies which isfourth row` in this case.
suppose that we created a funtion which accepts IndividualCustomerAccountId as the first parameter and CompanyCustomerAccountId as the second parameter
sample input
MyFunc(1 , 2) should return first and second rows
MyFunc(1 , 50) should return first and fourth rows because no company with CustomerAccountId 50 found in the table so retrieve the default value for companies which is the fourth row
MyFunc(100 , 2) should return second and third rows because no individual with customer account Id 100 is found so we get the default value for individuals which is the third row, and we have a company with customerAccountId 2, so we simply can retrive it from the table.
I want to create either a LINQ query or SQL function to achieve these results
You could try SQL function
CREATE TABLE Customer
(
CustomerAccountId int,
CustomerAccountType varchar(20),
DueDays int,
IsAdjustable bit,
isDefaultForIndividual bit,
isDefaultForCompany bit
)
INSERT INTO Customer VALUES
(1, 'Individual', 10, 1,0,0),
(2, 'Company', 20, 0,0,0),
(null, null, 5, 0,1,0),
(null, null, 30, 1,0,1)
GO
CREATE FUNCTION MyFunc
(
#IndividualCustomerAccountId int,
#CompanyCustomerAccountId int
)
RETURNs #result TABLE
(
CustomerAccountId int,
CustomerAccountType varchar(20),
DueDays int,
IsAdjustable bit,
isDefaultForIndividual bit,
isDefaultForCompany bit
)
BEGIN
INSERT INTO #result
SELECT CustomerAccountId , CustomerAccountType, DueDays, IsAdjustable, isDefaultForIndividual,isDefaultForCompany
FROM Customer c
WHERE (CustomerAccountId = #IndividualCustomerAccountId AND CustomerAccountType = 'Individual')
OR (CustomerAccountId = #CompanyCustomerAccountId AND CustomerAccountType = 'Company')
IF(NOT EXISTS (SELECT 1 FROM Customer c
WHERE CustomerAccountId = #IndividualCustomerAccountId AND CustomerAccountType = 'Individual' ))
BEGIN
INSERT INTO #result
SELECT CustomerAccountId , CustomerAccountType, DueDays, IsAdjustable, isDefaultForIndividual,isDefaultForCompany
FROM Customer c
WHERE CustomerAccountId IS NULL AND isDefaultForIndividual = 1
END
IF(NOT EXISTS (SELECT 1 FROM Customer c
WHERE CustomerAccountId = #CompanyCustomerAccountId AND CustomerAccountType = 'Company' ))
BEGIN
INSERT INTO #result
SELECT CustomerAccountId , CustomerAccountType, DueDays, IsAdjustable, isDefaultForIndividual,isDefaultForCompany
FROM Customer c
WHERE CustomerAccountId IS NULL AND isDefaultForCompany = 1
END
RETURN;
END
GO
SELECT * from dbo.MyFunc(1,2)
SELECT * from dbo.MyFunc(1,50)
SELECT * from dbo.MyFunc(100,2)
SELECT * from dbo.MyFunc(100,50)
--DROP TABLE Customer
Demo link: Rextester
Basically, you can run an IF Exists with your query to see if there is going to be any data. If so, go ahead and run your query. If not, do a select default row.
If Exists (your query)
(your query)
Else
SELECT 'query for default row'
I hope its clear your problem.
Happy Coding.Thanks

duplicating 3 lines in sql server but changing the Period id

On my web app in visual studio web forms I am creating, it is pushing and pulling data from a SQL Server database. I need help with a problem i have run into. On the rates page, is a gridview that displays the rates for the current period, there are 6 columns in total.
I need to put a button that would when clicked copy/duplicate the last 3 lines being Period_Id, Description, Rate1, Rate2, Rate3, Rate4 . The problem is the period Id, for every 3 lines it is assigned 1 Id IE.
Period_Id, Description, Rate1,Rate2,Rate3,Rate4
1 , Example , 7 , 6 , 7 , 0
1 , Example ,8 , 4 ,1 , 100
1 , Example ,8 , 4 ,1 , 400
When the lines are copied the Period_Id Must change but follow the sequence of 1,1,1 and become 2,2,2 when copied again become 3,3,3 and keep the other data associated to it.
First of all, you should have a Primary Key defined for the table.
Secondly, you can do this by following these steps.
Create a Stored Proc in SQL Server DB
Call the below Stored Proc from your Application.
`
Create Procedure CopyRates
#PeriodID INT
AS
BEGIN
//Populate a temp table with all the values you want to copy from <YOURTABLE>
CREATE TABLE #TestData (Period_Id int, Description varchar(10), Rate1 int, Rate2 int, Rate3 int, Rate4 int)
INSERT INTO #TestData (Period_Id, Description, Rate1, Rate2, Rate3, Rate4)
VALUES
(Select PeriodID, Descriptiom Rate1, Rate2, Rate3, Rate4)
From <YOURTABLE>
Where PeriodID = #PeriodID
)
INSERT INTO <YOURTABLE> (Period_Id, Description, Rate1, Rate2, Rate3, Rate4)
SELECT Period_Id +1, Description,Rate1, Rate2, Rate3, Rate4
FROM #TestData
END
If you're just wanting to insert this data into the table with just period_id being changed you can do a simple insert into with a select.
Sample Data;
CREATE TABLE #TestData (Period_Id int, Description varchar(10), Rate1 int, Rate2 int, Rate3 int, Rate4 int)
INSERT INTO #TestData (Period_Id, Description, Rate1, Rate2, Rate3, Rate4)
VALUES
(1,'Example',7,6,7,0)
,(1,'Example',8,4,1,100)
,(1,'Example',8,4,1,400)
Your insert statement would be something like this;
INSERT INTO #TestData (Period_Id, Description, Rate1, Rate2, Rate3, Rate4)
SELECT Period_Id +1
,Description
,Rate1
,Rate2
,Rate3
,Rate4
FROM #TestData
And your results will look like this;
Period_Id Description Rate1 Rate2 Rate3 Rate4
1 Example 7 6 7 0
1 Example 8 4 1 100
1 Example 8 4 1 400
2 Example 7 6 7 0
2 Example 8 4 1 100
2 Example 8 4 1 400

Mysql normalization? Or another way?

After reading up on some normalization, it seems I am not quite grasping the concept.
What I am attempting to do is create a table that holds information for an item raffle.
So information for the item is ItemName, and Defindex.
After that, I need to have the "tickets" for the raffle, and to which user they went to. I want to limit the number of tickets sold.
So TicketA, TicketB, TicketC, TicketD.
Is there a query that I can use to insert a player name into TicketA if it's not full, or TicketB if A is full, so on until all tickets are sold?
Here's a sample to get you started: SQL Fiddle
Setup the basic tables to keep track of raffles and tickets.
CREATE TABLE Raffle
(
Id BIGINT AUTO_INCREMENT NOT NULL PRIMARY KEY
,Name VARCHAR(50) NOT NULL
,WinnerLimit INT NOT NULL
);
CREATE TABLE RaffleTicket
(
Id BIGINT AUTO_INCREMENT NOT NULL PRIMARY KEY
,RaffleId BIGINT NOT NULL
,UserId BIGINT NOT NULL
);
Setup a view to determine whether a raffle has any tickets left.
CREATE VIEW RaffleStatus
AS
SELECT Id AS RaffleId,
CASE WHEN EXISTS
(
SELECT 1
FROM RaffleTicket rt
WHERE rt.RaffleId = r.Id
GROUP BY rt.RaffleId
HAVING COUNT(rt.RaffleId) = r.WinnerLimit
)
THEN 1
ELSE 0
END AS SoldOut
FROM Raffle r;
Create a procedure to prevent overselling tickets. Note this probably isn't safe for multithreaded use.
DELIMITER //
CREATE PROCEDURE InsertRaffleTicket (IN userId BIGINT, IN raffleId BIGINT)
BEGIN
INSERT INTO RaffleTicket(UserId, RaffleId)
SELECT userId, raffleId
FROM RaffleStatus rs
WHERE rs.RaffleId = raffleId
AND rs.SoldOut = 0;
END//
DELIMITER ;
I want to limit the number of tickets sold.
That is business logic, not something that should reside in your database.
What if you want to query all raffles user X has attended? select * from raffles where ticketA = 'UserX' or ticketB = 'UserX' or ticketC = 'UserX'...
Just normalize it and check the ticket count from code.
One table of people, one of tickets, one of raffles.
Each ticket has the ID of the person and of the raffle.
As the previous answer, beyond that is business logic that shouldn't be in the DB. At most, you should "release" a batch of tickets for a raffle by creating them in the tickets table and then when a person wants to buy one you take the first ticket with the correct raffle ID and a null person ID.

How to default database value when system date change

I'm currently doing a banking website for my project, using C# and asp.net. One of the function is 'Remaining Daily Limit'. I need the database value to change back to default once I changed the system date to another day. Example : If a user had $500 (default value) as a daily limit, and he used all up. The next day, he will have $500 again. May I know how should I go about it?
Here is a SQL script that will create how I would setup your db with some sample data:
CREATE TABLE tblBankCustomer
(
BankCustomerId INT NOT NULL IDENTITY(1,1) PRIMARY KEY
, FirstName NVARCHAR(100) NOT NULL
, LastName NVARCHAR(100) NOT NULL
, DailySpendingLimit DECIMAL(38, 2) NOT NULL CONSTRAINT DF_tblBankCustomer_DailySpendingLimit DEFAULT(500)
)
CREATE TABLE tblTransactionType
(
TransactionTypeId INT NOT NULL IDENTITY(1,1) PRIMARY KEY
, TransactionType VARCHAR(50) NOT NULL
)
INSERT tblTransactionType (TransactionType)
VALUES ('Deposit')
, ('Withdrawal')
CREATE TABLE tblTransaction
(
TransactionId INT NOT NULL IDENTITY(1,1) PRIMARY KEY
, BankCustomerId INT NOT NULL
, TransactionDate DATE NOT NULL
, Amount DECIMAL(38, 2) NOT NULL
, TransactionTypeId INT NOT NULL
)
ALTER TABLE tblTransaction
ADD CONSTRAINT FX_tblTransaction_tblBankCustomer
FOREIGN KEY (BankCustomerId)
REFERENCES tblBankCustomer(BankCustomerId)
ALTER TABLE tblTransaction
ADD CONSTRAINT FX_tblTransaction_tblTransactionType
FOREIGN KEY (TransactionTypeId)
REFERENCES tblTransactionType(TransactionTypeId)
INSERT tblBankCustomer
(
FirstName
, LastName
)
VALUES ('Jeremy', 'Pridemore')
, ('K', 'YQ')
INSERT tblTransaction
(
BankCustomerId
, TransactionDate
, Amount
, TransactionTypeId
)
VALUES
(1, CURRENT_TIMESTAMP, 48.50, 2) -- Jeremy, Today, $48.50, Withdrawal
, (1, CURRENT_TIMESTAMP, 300.00, 2) -- Jeremy, Today, $300, Withdrawal
, (1, CURRENT_TIMESTAMP, -200.00, 1) -- Jeremy, Today, $200, Deposit
, (2, CURRENT_TIMESTAMP, 285.00, 2) -- K, Today, $285, Withdrawal
, (2, CURRENT_TIMESTAMP, 215.00, 2) -- K, Today, $215, Withdrawal
GO
CREATE FUNCTION fGetRemainingSpendingLimit
(
#BankCustomerId INT
, #Date DATE
)
RETURNS DECIMAL(38, 2)
BEGIN
SET #Date = ISNULL(#Date, CURRENT_TIMESTAMP)
DECLARE #RemainingLimit DECIMAL(38, 2) =
(SELECT
SUM([Transaction].Amount)
FROM tblBankCustomer Customer
INNER JOIN tblTransaction [Transaction]
ON [Transaction].BankCustomerId = Customer.BankCustomerId
AND [Transaction].TransactionDate = #Date
INNER JOIN tblTransactionType TransactionType
ON TransactionType.TransactionTypeId = [Transaction].TransactionTypeId
AND TransactionType.TransactionType = 'Withdrawal'
WHERE Customer.BankCustomerId = #BankCustomerId)
RETURN #RemainingLimit
END
GO
-- Some sample selects
SELECT dbo.fGetRemainingSpendingLimit(1, NULL)
SELECT dbo.fGetRemainingSpendingLimit(2, NULL)
Then in C# you should know the customer's ID for the customer you're working with. If you're using somethiing like ADO.NET you can call this function directly and use the value in code.
Default values are usually stay in some config file. In your specific case, I would say that you can
or have a table with default values
or in the tables where is possible to have restore functionality have default column with corresponding values.
after, can restore them using some stored procedure.
You can create SQL job and schedule it to run every midnight, within the job you can execute a stored procedure reseting values to $500.
In my opinion, based on that there may be other requirements in the future, I'd have a table that looks like:
UserID AppliedOn Limit
1 1/1/2012 500
1 2/1/2012 750
This give you a historic view of limits, that you can give to the user or data-mine. In the same way, that is how I would apply current daily limits.
UserID AppliedOn Withdrawn
1 1/10/2012 125
1 1/10/2012 225
Now on 1/1/2012 it would be easy to determine what the amount left in the limit is without any jobs or triggers. And again you'd have historic values that can be data-mined for other features.
SELECT
ul.Limit - uw.Sum as LimitLeft
FROM
UserLimit ul
INNER JOIN (
SELECT
UserID,
AppliedOn,
SUM(Limit) as Sum
FROM
UserLimit
Group by
UserID,
AppliedOn) uw on ul.UserID = uw.UserID
and ul.AppliedOn = uw.AppliedOn
WHERE
ul.UserID = #userID
AND ul.AppliedOn = #dateInQuestion
(my raw SQL skills might be a bit rusty due to Entity Framework here).

Create table and insert rows based on multiple select statements in SQL Server 2008

My situation is after login my website I wanted to show how many employees active, inactive & also for department wise, collage wise employees list of counts.
For that I created a procedure to create temporary table if it is not exist else drop table create temporary table, after that I wrote some SQL queries to get count of employees, department with conditions & then I'm inserting records to table.
Then I need the inserted rows. Now my problem is while executing procedure in SQL it executes but it's not creating & inserting any rows, I don't know why this happens. Please help me if any knows a solution to this problem.
My code:
alter proc SP_TEMPRECORDFORCOUNT
as
begin
IF (EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'TEMPRECORDFORCOUNT'))
BEGIN
drop table dbo.TEMPRECORDFORCOUNT
END
create table dbo.TEMPRECORDFORCOUNT(totalemployeecount int,activeemployeecount int,inactiveemployeecount int,deptwiseemployeecount int,activeemployeecount int)
declare #totalemployeecount int
declare #activeemployeecount int
declare #inactiveemployeecount int
declare #deptwiseemployeecount int
declare #activeemployeecount int
select #totalemployeecount =COUNT(*) from Employee
select #activeemployeecount =COUNT(*) from Employee where status=1
select #inactiveemployeecount =COUNT(*) from Employee where status=0
select #deptwiseemployeecount = count(*) from Department where e_id !=null
select #activeemployeecount = count(*) from Department d inner join Employee e on d.e_id =e.e_id where status_id=1
insert into TEMPRECORDFORCOUNT
(
totalemployeecount
,activeemployeecount
,inactiveemployeecount
,deptwiseemployeecount
,activeemployeecount
)
values
(
#totalemployeecount ,
#activeemployeecount ,
#inactiveemployeecount ,
#deptwiseemployeecount ,
#activeemployeecount ,
)
end
is it correct way thing i'm doing? if not please correct me.
With SQL Server 2008 R2 you have the option for table variables.
So your statement should be changed to the following:
DECLARE #TEMPRECORDFORCOUNT TABLE(totalemployeecount int,activeemployeecount int,inactiveemployeecount int,deptwiseemployeecount int,activeemployeecount int)
insert into #TEMPRECORDFORCOUNT
(
totalemployeecount
,activeemployeecount
,inactiveemployeecount
,deptwiseemployeecount
,activeemployeecount
)
values
(
#totalemployeecount ,
#activeemployeecount ,
#inactiveemployeecount ,
#deptwiseemployeecount ,
#activeemployeecount ,
)
SELECT * FROM #TEMPRECORDFORCOUNT
;

Categories

Resources