Make Procedure with SCOPE_IDENTITY() - asp.net

I got this three tables
CREATE TABLE
(
FirstTableId Int primary key identity,
Something nvarchar(20)
)
CREATE TABLE SecondTable
(
SecondTableId Int primary key identity,
Something nvarchar(20)
)
CREATE TABLE Relation
(
RelationId int primary key identity,
RelationSomething nvarchar(20),
FirstTableId Int,
SecondTableId Int,
FOREIGN KEY (FirstTableId) REFERENCES FirstTable(FirstTableId),
FOREIGN KEY (SecondTableId) REFERENCES SecondTable(SecondTableId),
)
I create this procedure to insert data into FirstTable and Relation:
CREATE PROC InsertInto (#FirstTableId int)
AS
INSERT INTO FirstTable VALUES ('example')
SELECT #FirstTableId = SCOPE_IDENTITY()
INSERT INTO Relation (RelationSomething, FirstTableId, SecondTableId) VALUES ('example', #FirstTableId, 2)
I pass values from dropdownlists for example data, and do not pass anything for #FirstTable, because I expect that it get SCOPE_IDENTITY(), but I got error like this: "Must declare the scalar variable "#FirstTableId"? How can I solve this and make it's work?

You need to declare the variable in the body and not the Stored Procedure definition. When you declare it in the definition, that means you will pass the value when you call the Stored Procedure.
CREATE PROC InsertInto ()
AS
DECLARE #FirstTableId int;
INSERT INTO FirstTable VALUES ('example')
SET #FirstTableId = SCOPE_IDENTITY()
INSERT INTO Relation (RelationSomething, FirstTableId, SecondTableId) VALUES ('example', #FirstTableId, 2)

Do you have a typo in your actual code? Because in your question you say the procedure parameter is #FirstTable and then later say the error is about #FirstTableId, and in the example procedure the name of the parameter is #FirstTableId.
If you do not need to input or output anything from the parameter, declare and use the variable in the procedure.
If you are trying to use an output parameter, then you would declare the parameter as output:
create proc InsertInto (#FirstTableId int output) as
begin;
set nocount, xact_abort on;
insert into FirstTable
values ('example');
select #FirstTableId = scope_identity();
insert into Relation (FirstTableId, SecondTableId) values
(#FirstTableId, 2);
end;
go
and use it like so:
declare #id int;
exec insertinto #id output;
select #id as IdOutput;
returns
+----------+
| IdOutput |
+----------+
| 1 |
+----------+
and the row from the relation table:
select * from relation;
returns
+--------------+---------------+
| firsttableid | secondtableid |
+--------------+---------------+
| 1 | 2 |
+--------------+---------------+
rextester demo: http://rextester.com/VPS78362

Related

Auto Increment varchar datatype set as primary key

I have created a table with an Id column as varchar(20).
I need a stored procedure which can increment id by 1.
I have tried this:
ALTER PROCEDURE dbo.spInsertCatQuery
(#Users_Id varchar(20),
#Cat_Id varchar(20),
#Query varchar(100),
#Query_Title varchar(50)
)
AS
BEGIN
Declare #Query_Id bigint
SELECT #Query_Id = coalesce((select max(Query_Id) + 1 from tblCatQuery), 1);
INSERT INTO tblCatQuery
VALUES(#Query_Id, #Users_Id, #Cat_Id, #Query_Title, #Query)
END
But it is not working after 10th record.
Change the selection of Query_id from your table to below
SELECT #Query_Id=
coalesce((select max(cast(Query_Id as int)) + 1 from tblCatQuery), 1);
Based on Gordon's comment; my understanding is that since ID is varchar max(id) is not fetching the correct max value but casting it will do so.
For example try this
create table testtab (id varchar(10));
insert into testtab values(2),(200),(53)
If you say below it will return 53
select MAX(id) from testtab
but this one will return 200
select MAX(cast(id as int)) from testtab
Tested in SQL SERVER 2008 R2
You do know your stored procedure has an implicit race condition, don't you?
Between your calculating the new query id and your table insert getting committed, another session can come in, get exactly the same query id, insert it and get committed. Guess what happens when your insert tries to commit? First in wins; the second gets a duplicate key error. Don't ask me how I know this :)
If you really need a text query id, you might try using a computed field, something like this:
create table dbo.tblCatQuery
(
query_id int not null identity(1,1) primary key clustered ,
query_id_text as right('0000000000'+convert(varchar,id),10) ,
user_id varchar(20) not null ,
cat_id varchar(20) not null ,
query varchar(100) not null ,
query_title varchar(50) not null ,
)
Then your stored procedure looks like this:
create procedure dbo.spInsertCatQuery
#Users_Id varchar(20) ,
#Cat_Id varchar(20) ,
#Query varchar(100) ,
#Query_Title varchar(50) ,
#Query_ID varchar(10) output
AS
insert dbo.tblCatQuery ( user_id , cat_id , query_title , query )
VALUES ( #Users_Id , #Cat_Id , #Query_Title , #Query )
-- give the caller back the id of the row just inserted
set #Query_ID = ##SCOPE_IDENTITY
-- for redundancy, hand it back as the SP's return code, too
return #Query_ID
GO
It sounds like your application needs a string for the ID field, yet in the database you want it ID to behave as an auto-incrementing integer field.
Consider using an integer in the database, and when you retrieve the value and need to use it as as string, at that point convert the value to a string, either in your query or in your application.
This will solve your problem.
You must seriously review your design. I shall suggest something like this.
CREATE TABLE tblCatQuery(QueryId int NOT NULL PRIMARY KEY IDENTITY(1, 1),
UserId int NOT NULL REFERENCES tblUsers(UserId),
CatId int NOT NULL REFERENCES tblCat(CatId),
Query varchar(100), Query_Title varchar(50))
CREATE TABLE tblUsers(UserId int NOT NULL PRIMARY KEY IDENTITY(1, 1), ....
CREATE TABLE tblCat(CatId int NOT NULL PRIMARY KEY IDENTITY(1, 1), ....
CREATEPROCEDURE dbo.spInsertCatQuery
(
#Users_Id int,
#Cat_Id int,
#Query varchar(100),
#Query_Title varchar(50)
)
AS
BEGIN
INSERT INTO tblCatQuery(Users_Id, Cat_Id, Query_Title, Query)
VALUES( Users_Id, Cat_Id, Query_Title, Query)
END

How to autogenerate the username with specific string?

I am using asp.net2008 and MY SQL.
I want to auto-generate the value for the field username with the format as
"SISI001", "SISI002",
etc. in SQL whenever the new record is going to inserted.
How can i do it?
What can be the SQL query ?
Thanks.
Add a column with auto increment integer data type
Then get the maximum value of that column in the table using "Max()" function and assign the value to a integer variable (let the variable be 'x').
After that
string userid = "SISI";
x=x+1;
string count = new string('0',6-x.ToString().length);
userid=userid+count+x.ToString();
Use userid as your username
Hope It Helps. Good Luck.
PLAN A>
You need to keep a table (keys) that contains the last numeric ID generated for various entities. This case the entity is "user". So the table will contain two cols viz. entity varchar(100) and lastid int.
You can then have a function written that will receive the entity name and return the incremented ID. Use this ID concatenated with the string component "SISI" to be passed to MySQL for insertion to the database.
Following is the MySQL Table tblkeys:
CREATE TABLE `tblkeys` (
`entity` varchar(100) NOT NULL,
`lastid` int(11) NOT NULL,
PRIMARY KEY (`entity`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
The MySQL Function:
DELIMITER $$
CREATE FUNCTION `getkey`( ps_entity VARCHAR(100)) RETURNS INT(11)
BEGIN
DECLARE ll_lastid INT;
UPDATE tblkeys SET lastid = lastid+1 WHERE tblkeys.entity = ps_entity;
SELECT tblkeys.lastid INTO ll_lastid FROM tblkeys WHERE tblkeys.entity = ps_entity;
RETURN ll_lastid;
END$$
DELIMITER ;
The sample function call:
SELECT getkey('user')
Sample Insert command:
insert into users(username, password) values ('SISI'+getkey('user'), '$password')
Plan B>
This way the ID will be a bit larger but will not require any extra table. Use the following SQL to get a new unique ID:
SELECT ROUND(NOW() + 0)
You can pass it as part of the insert command and concatenate it with the string component of "SISI".
I am not an asp.net developer but i can help you
You can do something like this...
create a sequence in your mysql database as-
CREATE SEQUENCE "Database_name"."SEQUENCE1" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 001 START WITH 21 CACHE 20 NOORDER NOCYCLE ;
and then while inserting use this query-----
insert into testing (userName) values(concat('SISI', sequence1.nextval))
may it help you in your doubt...
Try this:
CREATE TABLE Users (
IDs int NOT NULL IDENTITY (1, 1),
USERNAME AS 'SISI' + RIGHT('000000000' + CAST(IDs as varchar(10)), 4), --//getting uniqueness of IDs field
Address varchar(150)
)
(not tested)

scope identity in stored procedure

I have got the following stored procedure.
ALTER PROCEDURE dbo.insert_movie
(
#first_name varchar(50),
#movie_name varchar(50),
#date date,
#last_id_inserted int,
#last_name varchar(50)
)
AS
INSERT INTO movies (movie_name,movie_date) VALUES (#movie_name,#date);
SELECT SCOPE_IDENTITY() AS scope;
INSERT INTO customer (first_name,last_name,movie_id)
VALUES (#first_name,#last_name,#last_id_inserted)
I want to insert the scope variable into #last_id_inserted.
Basically, I want to insert the last inserted id (movie_id) to the customer table..
not sure about the syntax though
You can assign the result of the function to the variable.
SET #last_id_inserted = SCOPE_IDENTITY();
There is no need to have #last_id_inserted as a parameter. Declare it as a variable in the SP.
DECLARE #last_id_inserted int;
SET #last_id_inserted = SCOPE_IDENTITY();
Or you can use it directly in the insert statement.
INSERT INTO customer (first_name,last_name,movie_id)
VALUES (#first_name,#last_name,SCOPE_IDENTITY())
SELECT #last_id_inserted = SCOPE_IDENTITY()
or
SET #last_id_inserted = SCOPE_IDENTITY()
You need to declare the variable in the stored procedure and assign the value of the SCOPE_IDENTITY function:
DECLARE #last_id_inserted int;
SET #last_id_inserted = SCOPE_IDENTITY();
I just want to add to other answers that you can add OUTPUT clause (SQLServer 2005 and higher) to your INSERT instead of using SCOPE_IDENTITY

Passing comma-separated value from .NET to stored procedure using the value in "IN" SQL function

I have an SQL query similar to the following:
create procedure test
(
#param1 nvarchar(max)
)
as
begin
select * from table where column1 in (#param1)
end
Now I need to pass the value of #param1 from my .net application in such a way that the above query works.
Can some one please advise me on how to pass from my VB.NET code a value which is similiar to below:
'1','2','3'
My main question is how do I structure value of parameter like above example from my .NET application?
quickly like that, I would create a table valued function that would parse it so you can do
select *
from table
where field in (select field from dbo.myfunction(#param1))
For this type of thing, I use this function and use it as follows:
select Column1, column2 from my table where ID in (select item from fnSplit('1,2,3,4,5,6',','))
create FUNCTION [dbo].[fnSplit](
#sInputList VARCHAR(8000) -- List of delimited items
, #sDelimiter VARCHAR(8000) = ',' -- delimiter that separates items
)
RETURNS #List TABLE (item VARCHAR(8000))
BEGIN
DECLARE #sItem VARCHAR(8000)
WHILE CHARINDEX(#sDelimiter,#sInputList,0) <> 0
BEGIN
SELECT
#sItem=RTRIM(LTRIM(SUBSTRING(#sInputList,1,CHARINDEX(#sDelimiter,#sInputList,0)-1))),
#sInputList=RTRIM(LTRIM(SUBSTRING(#sInputList,CHARINDEX(#sDelimiter,#sInputList,0)+LEN(#sDelimiter),LEN(#sInputList))))
IF LEN(#sItem) > 0
INSERT INTO #List SELECT #sItem
END
IF LEN(#sInputList) > 0
INSERT INTO #List SELECT #sInputList -- Put the last item in
RETURN
END
I don't think the problem is in the values you are passing. #param1 is just a string.
You need to address this in your procedure. Your select statement will not be able to recognize the values in you IN clause. One solution is to take the comma-separated string and insert each record into a table variable Explained Here
If your table variable is table #param_list, you procedure test looks like:
create procedure test ( #param1 nvarchar(max) )
as begin
select * from table where column1 in (Select thefield from #param_list);
end

problem with sql table updation

I have 2 tables
CREATE TABLE PODRAS_MS.tbl_FieldWorkers
(
[FWInsOnServerID] INT NOT NULL IDENTITY(1,1),
[BaseStationID] INT NOT NULL,
[RefID] INT NOT NULL,
[DisSubInsID] INT NOT NULL,
[FieldWorkerID] CHAR(7) NOT NULL,
[LastRecDate] DATETIME NOT NULL,
)
ALTER TABLE PODRAS_MS.tbl_FieldWorkers ADD CONSTRAINT PK_FieldWorkers_FWInsOnServerID PRIMARY KEY([FWInsOnServerID])
ALTER TABLE PODRAS_MS.tbl_FieldWorkers ADD CONSTRAINT FK_FieldWorkers_DisSubInsID FOREIGN KEY([DisSubInsID]) REFERENCES PODRAS_MS.tbl_DisasterSubInstances([SubInsID]) ON UPDATE CASCADE ON DELETE NO ACTION
ALTER TABLE PODRAS_MS.tbl_FieldWorkers ADD CONSTRAINT FK_FieldWorkers_BaseStationID FOREIGN KEY([BaseStationID]) REFERENCES PODRAS_MS.tbl_BaseStations([BaseStationID]) ON UPDATE CASCADE ON DELETE NO ACTION
ALTER TABLE PODRAS_MS.tbl_FieldWorkers ADD CONSTRAINT DF_FieldWorkers_LastRecDate DEFAULT(GETDATE()) FOR [LastRecDate]
GO
CREATE TABLE PODRAS_MS.tbl_FieldWorkerNodeGPSLocations
(
[FWNStatID] INT NOT NULL IDENTITY(1,1),
[FWInsOnServerID] INT NOT NULL,
[Latitude] DECIMAL(20,17) NOT NULL,
[Longitude] DECIMAL(20,17) NOT NULL,
[UpdateOn] DATETIME NOT NULL,
)
ALTER TABLE PODRAS_MS.tbl_FieldWorkerNodeGPSLocations ADD CONSTRAINT PK_FieldWorkerNodeGPSLocations_FWNStatID PRIMARY KEY([FWNStatID])
ALTER TABLE PODRAS_MS.tbl_FieldWorkerNodeGPSLocations ADD CONSTRAINT FK_FieldWorkerNodeGPSLocations_FWInsOnServerID FOREIGN KEY([FWInsOnServerID]) REFERENCES PODRAS_MS.tbl_FieldWorkers([FWInsOnServerID]) ON UPDATE CASCADE ON DELETE NO ACTION
ALTER TABLE PODRAS_MS.tbl_FieldWorkerNodeGPSLocations ADD CONSTRAINT DK_FieldWorkerNodeGPSLocations_UpdateOn DEFAULT(GETDATE()) FOR [UpdateOn]
GO
Both tables are updated through a webservice in the 1st table all the fields can be inserted through the web service but in the second table only data for [Latitude],[Longitude],[UpdateOn] fields comes through the webservice.so my problem is how can i insert the values to [FWInsOnServerID] field since its not comes through the webservice and its a reference for the 1st table???
If I understand you correctly, the insert in the second table is dependant on the result of the insert in your first table?
In this case, you could simply return the generted ID of the first table and use that result to insert into the second table.
Something like (if you're using Stored Procedures).
SELECT SCOPE_IDENTITY()
at the end of your stored procedure. And then in your .NET code which handles the database code, use that number to do the second insert.
You could do it all in a single stored procedure like this:
CREATE PROCEDURE PODRAS_MS.insert_FieldWorker()
#BaseStationID INT,
#RefID INT,
#DisSubInsID INT,
#FieldWorkerID CHAR(7),
#Latitude DECIMAL(20,17),
#Longitude DECIMAL(20,17)
AS
BEGIN
INSERT INTO
PODRAS_MS.tbl_FieldWorkers
([BaseStationID], [RefID], [DisSubInsID], [FieldWorkerID])
VALUES (#BaseStationID, #RefID, #DisSubInsID, #FieldWorkerID)
DECLARE #FWInsOnServerID INT
SELECT #FWInsOnServerID = SCOPE_IDENTITY()
INSERT INTO PODRAS_MS.tbl_FieldWorkerNodeGPSLocations
([FWInsOnServerID], [Latitude], [Longitude])
VALUES (#FWInsOnServerID, #Latitude, #Longitude)
END
You could then select the records from the same stored procedure, but it is more common to separate this out into another stored proc.
EDIT: use an output parameter
CREATE PROCEDURE PODRAS_MS.insert_FieldWorker()
#BaseStationID INT,
#RefID INT,
#DisSubInsID INT,
#FieldWorkerID CHAR(7),
#FWInsOnServerID INT output
AS
BEGIN
INSERT INTO
PODRAS_MS.tbl_FieldWorkers
([BaseStationID], [RefID], [DisSubInsID], [FieldWorkerID])
VALUES (#BaseStationID, #RefID, #DisSubInsID, #FieldWorkerID)
SELECT #FWInsOnServerID = SCOPE_IDENTITY()
END

Resources