I Have registration Form (asp.net) that include for text box . one of them is email text box . and iam using Linq To SQL .
i have been write procedure to forbid duplication
CREATE PROCEDURE CheckEmail ( #email NVARCHAR(50) )
AS
BEGIN
SET NOCOUNT ON;
IF NOT EXISTS ( SELECT C.Email
FROM Customer C
WHERE Email = #email )
BEGIN
INSERT INTO Customer
( Email )
VALUES ( #email )
END
ELSE
BEGIN
ROLLBACK TRANSACTION
END
END
is this a good way? How can I return error?
You can use RAISEERROR() function to return error. Also because you never tried to insert a duplicate email you do not need to ROLLBACK
CREATE PROCEDURE CheckEmail ( #email NVARCHAR(50) )
AS
BEGIN
SET NOCOUNT ON;
IF NOT EXISTS ( SELECT C.Email
FROM Customer C
WHERE Email = #email )
BEGIN
INSERT INTO Customer
( Email )
VALUES ( #email )
END
ELSE
BEGIN
DECLARE #ErrorMessage VARCHAR(100) = 'ERROR: Attempt to insert duplicate email address'
RAISERROR (#ErrorMessage,11,1)
RETURN
END
END
this is assuming you using sql-server if you are using a different DBMS just look up raise error function for your system.
Note: When you return SQL Error you need to make sure that application code knows how to handle it instead of just crashing.
Related
I have a stored procedure to validate a user. After validate right now I am returning true if user is validated but how can I return all the details of that user instead of true?
IF (#Flag='Authenticate')
BEGIN
IF EXISTS(SELECT UserID FROM UserInformation WITH(NOLOCK)WHERE UserName=#UserName and Password=#UserPassword )
BEGIN
INSERT INTO UserLoginHistory(UserId,LastLoggedIn)
SELECT #Userid,GETDATE()
select 'true' as [Output]
END
END
Try something like below query - You can declare more variables as needed, and store all those information in variables which you want to return.
IF (#Flag='Authenticate')
BEGIN
Declare #UserID varchar(50) = null
SELECT #UserID = UserID FROM UserInformation WITH(NOLOCK) WHERE UserName=#UserName and Password=#UserPassword )
IF (#UserID is not NULL)
BEGIN
INSERT INTO UserLoginHistory(UserId,LastLoggedIn)
SELECT #Userid,GETDATE()
SELECT #Userid
END
END
You don't need a separate "if" to check if the user already exists. You can put that all into a single query:
IF (#Flag = 'Authenticate')
BEGIN
INSERT INTO UserLoginHistory(UserId, LastLoggedIn)
SELECT v.Userid, GETDATE()
FROM (VALUES (#UserId)) v(UserId)
WHERE EXISTS (SELECT 1
FROM UserInformation ui
WHERE ui.UserName = #UserName AND ui.Password = #UserPassword
);
SELECT ui.*
FROM UserInformation ui
WHERE ui.UserName = #UserName AND ui.Password = #UserPassword;
END;
Also, I am concerned about #UserPassword. Hopefully that value is encrypted! You should not have clear-text passwords anywhere in an application that has a user other than you -- even for a demo or course.
So yea. I have this really weird problem. I have the following stored procedure
ALTER PROCEDURE [CP24SHOP].[sp_part_set_status_bulk]
#user nvarchar(max),
#doerTicket VARCHAR ( 200 ) = null,
#status int,
#items CP24SHOP.udt_parts READONLY
AS
BEGIN
SET NOCOUNT ON;
-- Check security
exec websocket.sp_validate_user
#user,
#doerTicket out
-- foreach row in #items, update the status
MERGE INTO [file].ItemPart WITH ( XLOCK, ROWLOCK ) AS target
USING ( SELECT
item.GID
FROM #items AS item
) AS source
ON ( target.GID = source.GID )
WHEN MATCHED THEN
UPDATE SET
target.[Status] = #status,
target.DateTimeModified = GETDATE();
select 'bob'
RETURN 0
END
and when I run it from Management Studio with this code
declare #user nvarchar(max) = 'websocket'
DECLARE #list CP24SHOP.udt_parts
INSERT INTO #list
(
GID
)
VALUES
(
-7228376
)
select [Status] from [file].ItemPart
where GID = -7228376
exec CP24SHOP.sp_part_set_status_bulk
#user = #user,
#items = #list,
#status = '155'
select [Status], DateTimeModified from [file].ItemPart
where GID = -7228376
it updates the status without problem
but when calling it through our websocket it runs the code and returns "bob" as it should, but when I check the database the status of the item hasn't updated. I'm clueless as to what might be wrong
err - I think you're missing a commit.
Looks to me like you are updating & then rolling back!
I need to find out who is deleting / updating the data on table THETABLE, the time, using what program, and the command that is sent to the database that caused the modification.
From googling and asking some colleagues, the recommended way is on delete trigger. I know how to create trigger, for example:
create trigger whodunit
on THETABLE
for delete
as begin
insert into MyAuditTbl(moddate, ...
end
But how do I get the command that is sent to the DB (query / stored procedure), application name, IP address, etc.?
I found some script and customized it to fit my needs:
create trigger AuditTHETABLE
on THETABLE
for delete, update
as begin
set nocount on
declare #shouldlog bit, #insertcount bigint, #deletecount bigint
select
#shouldlog = 1,
#insertcount = (select count(*) from inserted),
#deletecount = (select count(*) from deleted)
-- if no rows are changed, do not log
if #insertcount < 1 and #deletecount < 1 begin
select #shouldlog = 0
end
-- ... other checks whether to log or not
if #shouldlog = 1 begin
-- prepare variable to capture last command
declare #buffer table (
eventtype nvarchar(30),
parameters int,
eventinfo nvarchar(4000)
)
-- use DBCC INPUTBUFFER to capture last command
-- unfortunately only the first 255 characters are captured
insert #buffer
exec sp_executesql N'DBCC INPUTBUFFER(##spid) WITH NO_INFOMSGS'
declare #lastcommand varchar(max)
select #lastcommand = eventinfo from #buffer
-- insert into audit table
insert into myauditlog(
eventdate, tablename, hostname,
appname, insertcount, deletecount, command
) values(
getdate(),
'THETABLE',
host_name(),
app_name(),
#insertcount,
#deletecount,
#lastcommand
)
end
end
I wanted to write stored procedure for login table.
This procedure involves, checking if LogInID already exists, and if it exists then dont allow to insert record with same LogInID.
I procedure is as follows:
ALTER PROCEDURE logTRAN
#id varchar(25),
#pass varchar(25)
AS
BEGIN TRANSACTION
insert into login values(#id,#pass)
IF EXISTS (select count(*) from login where LogInID=#id)
BEGIN
PRINT 'USER ALREADY EXISTS'
ROLLBACK
END
ELSE
BEGIN
COMMIT TRANSACTION
END
I execute it as follows:
exec logTRAN '0L036','aaa' //this is repeated record with LogInID '0L036'
But Record gets inserted with following result:
(1 row(s) affected)
USER ALREADY EXISTS
Msg 266, Level 16, State 2, Procedure logTRAN, Line 0
Transaction count after EXECUTE indicates that a COMMIT or ROLLBACK TRANSACTION statement is missing. Previous count = 2, current count = 0.
What can be the mistake in my stored procedure?
Please guid me.
Change your SP to
CREATE PROCEDURE logTRAN
#id varchar(25),
#pass varchar(25)
AS
IF EXISTS (SELECT 1 FROM login WHERE LogInID = #id)
PRINT 'USER ALREADY EXISTS'
ELSE
INSERT INTO login VALUES(#id, #pass)
Here is SQLFiddle demo
On a side note: IMHO you don't need an SP for this at all. That what a UNIQUE constraint is for.
Change your query like below:
ALTER PROCEDURE logTRAN
(
#id varchar(25),
#pass varchar(25)
)
AS
BEGIN
IF EXISTS (SELECT LogInID from login where LogInID=#id)
BEGIN
PRINT 'User Already Exists'
END
ELSE
BEGIN
INSERT INTO login Values(#id,#pass)
END
END
RETURN
Or if you don't want to print just use:
ALTER PROCEDURE logTRAN
(
#id varchar(25),
#pass varchar(25)
)
AS
BEGIN
IF NOT EXISTS (SELECT LogInID from login where LogInID=#id)
BEGIN
INSERT INTO login Values(#id,#pass)
END
END
RETURN
I would recommend to use peterm's Answer. You should use SELECT 1 inplace of SELECT LogInID.
I wrote a stored procedure which returns contract status for anauthor. If author doesn't exist i'll return -900. So, this is what i did
CREATE PROCEDURE AUthorContract
#user varchar(10)
AS
IF(#user NOT IN(select Au_id from Authors))
BEGIn
RETURN -900
END
ELSE
BEGIN
select contract from from Authors where Au_id = #user
END
GO
However, when I give a valid author id as input, it returns -900 and if i give some id it goes into else and just returns 0 . So, I reversed them and entered correct id, but it still just returns 0 and not the contract value.
Can u please help me out the mistake i have been doing. The DB is pubs.
stored procedure can "return" three types of things:
int return value, via RETURN command
output parameter value, via parameter list: #YourPartameter anydatatype OUTPUT
result set: SELECT * FROM YourTable
your procedure does not have a RETURN command for normal exit, so it defaults to a value of zero. You need to check the result set in your application if the return value is zero.
try this to RETURN the contact value:
CREATE PROCEDURE AUthorContract
#user varchar(10)
AS
DECLARE #contract int
IF(#user NOT IN(select Au_id from Authors))
BEGIn
RETURN -900
END
ELSE
BEGIN
select #contract=contract from from Authors where Au_id = #user
END
RETURN #contract
GO
try this to use an OUTPUT parameter:
CREATE PROCEDURE AUthorContract
#user varchar(10), #contract varchar(30) OUTPUT
AS
IF(#user NOT IN(select Au_id from Authors))
BEGIn
RETURN -900
END
ELSE
BEGIN
select #contract=contract from from Authors where Au_id = #user
END
RETURN 0
GO
Here is the result set, with an explicit return:
CREATE PROCEDURE AUthorContract
#user varchar(10)
AS
IF(#user NOT IN(select Au_id from Authors))
BEGIn
RETURN -900
END
ELSE
BEGIN
select contract from from Authors where Au_id = #user
END
RETURN 0
GO
one way
CREATE PROCEDURE AUthorContract
#user varchar(10)
AS
IF NOT EXISTS(select 1 from Authors WHERE Au_id = #user )
BEGIN
SELECT -900 as contract -- this will return a result set
END
ELSE
BEGIN
select contract from Authors where Au_id = #user
END
GO
but a return status is not the same as a result set
if the proc is successful you will get 0, with return you can only use integers, use an output parameter if you need to return varchar
You're not returning the contract value. You are just selecting a scalar value to be outputed. The stored proc is returning 0 because it completed execution without a return value of something other than that.
Also, not sure if it is a typo, but you have an extra from in your select clause.
try:
IF(#user NOT IN(select Au_id from Authors))
BEGIn
declare #a int
set #a= -900
return #a
--print #a
END