Stored procedure only updates when running it from Management studio - sql

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!

Related

Subquery returns more than one value?

I'm trying to use a stored procedure I wrote that is supposed to create a new project in a "Project" table. It also checks to see if there is a saved project in a "Saved Project" table with the same ID and deletes it upon successful creation.
It's also supposed to check whether the user_id passed has permission to actually create a project( i.e. isn't a standard user).
Here is the stored procedure:
USE [BugMate_DB]
GO
/****** Object: StoredProcedure [dbo].[create_project] Script Date: 2020-07-08 11:05:30 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[create_project]
#project_name NVARCHAR(40),
#date_started DATETIME,
#project_description NVARCHAR(400),
#project_status NVARCHAR(40),
#project_active BIT,
#next_iteration_date DATETIME,
#created_by_userid INT,
#project_leader_id INT,
#save_id INT = NULL
AS
SET NOCOUNT ON
BEGIN
IF (SELECT TOP 1 roleid from user_info WHERE userid = #created_by_userid) = 'SDU'
BEGIN
RAISERROR ('User does not have permission to do this action. Please contact a manager or administrator to resolve this issue.', 16, 1)
END
ELSE
BEGIN
INSERT INTO project(project_name, date_started, project_description, project_status, project_active, next_iteration_date, created_by_userid, project_leader_id)
VALUES (#project_name, #date_started, #project_description, #project_status, #project_active, #next_iteration_date, #created_by_userid, #project_leader_id)
IF ##ERROR <> 0
BEGIN
RAISERROR('Project creation insert failed.', 16, 1)
END
ELSE
BEGIN
IF #save_id != NULL
BEGIN
IF EXISTS (SELECT TOP 1 save_id FROM saved_project WHERE save_id = #save_id)
BEGIN
DELETE FROM saved_project WHERE save_id = #save_id
END
END
END
END
IF ##ERROR <> 0
BEGIN
RAISERROR('Error creating project', 16, 1)
END
ELSE
BEGIN
INSERT INTO project_member(userid, project_number)
VALUES (#created_by_userid, (SELECT project_number FROM project WHERE created_by_userid = #created_by_userid))
END
END
The problem is that I am getting this error when execute my SP:
Msg 512, Level 16, State 1, Procedure create_project, Line 48
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
I'm not sure why any of my sub queries would be returning multiple values.
Here are the values I am trying to pass:
USE [BugMate_DB]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[create_project]
#project_name = N'Test',
#date_started = N'12/25/2015 12:00:00 AM',
#project_description = N'This is a test.',
#project_status = N'InDevelopment',
#project_active = 1,
#next_iteration_date = N'12/25/2015 12:00:00 AM',
#created_by_userid = 19,
#project_leader_id = 19,
#save_id = NULL
SELECT 'Return Value' = #return_value
GO
I have tried using "TOP 1" to try and get a single value back but it doesn't seem to be what I'm looking for.
As far as I can tell this isn't an issue of joins either.
I'm new to SQL Server so any help would be appreciated.
Try changing this
IF ( SELECT TOP 1 roleid from user_info WHERE userid = #created_by_userid ) = 'SDU'
BEGIN
RAISERROR ( 'User does not have permission to do this action. Please contact a manager or administrator to resolve this issue.', 16, 1 )
END
To
IF NOT EXISTS ( SELECT * FROM user_info WHERE userid = #created_by_userid AND roleid = 'SDU' )
BEGIN
RAISERROR ( 'User does not have permission to do this action. Please contact a manager or administrator to resolve this issue.', 16, 1 )
END
Edit: Include explicit role access.
IF NOT EXISTS ( SELECT * FROM user_info WHERE userid = #created_by_userid AND roleid IN ( 'SDU', 'MNG', 'ADM ' ) )
BEGIN
RAISERROR ( 'User does not have permission to do this action. Please contact a manager or administrator to resolve this issue.', 16, 1 )
END
Update:
USE [BugMate_DB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[create_project]
#project_name NVARCHAR(40),
#date_started DATETIME,
#project_description NVARCHAR(400),
#project_status NVARCHAR(40),
#project_active BIT,
#next_iteration_date DATETIME,
#created_by_userid INT,
#project_leader_id INT,
#save_id INT = NULL
AS
BEGIN
SET NOCOUNT ON;
DECLARE #err INT = 0;
DECLARE #output TABLE ( project_number INT );
IF NOT EXISTS ( SELECT * FROM user_info WHERE userid = #created_by_userid AND roleid IN ( 'SDU', 'MNG', 'ADM ' ) )
BEGIN
RAISERROR ( 'User does not have permission to do this action. Please contact a manager or administrator to resolve this issue.', 16, 1 );
END
ELSE
BEGIN
INSERT INTO project (
project_name, date_started, project_description, project_status, project_active, next_iteration_date, created_by_userid, project_leader_id
)
OUTPUT inserted.project_number INTO #output
VALUES (
#project_name, #date_started, #project_description, #project_status, #project_active, #next_iteration_date, #created_by_userid, #project_leader_id
);
-- Capture error value.
SET #err = ##ERROR;
IF #err <> 0
BEGIN
RAISERROR ( 'Project creation insert failed.', 16, 1 );
END
ELSE
BEGIN
IF #save_id IS NULL
BEGIN
IF EXISTS ( SELECT * FROM saved_project WHERE save_id IS NULL )
BEGIN
DELETE FROM saved_project WHERE save_id IS NULL;
END
END
END
END
IF #err <> 0
BEGIN
RAISERROR ( 'Error creating project', 16, 1 );
END
ELSE
BEGIN
INSERT INTO project_member (
userid, project_number
)
VALUES (
#created_by_userid,
( SELECT project_number FROM #output )
);
END
END
Please compare the NULL values using IS NULL like below:
IF #save_id IS NULL
or
IF #save_id IS NOT NULL
I haven't seen this type of query before
INSERT INTO project_member(userid, project_number)
VALUES (#created_by_userid,
(SELECT project_number FROM project WHERE created_by_userid = #created_by_userid))
I would do either
INSERT INTO project_member(userid, project_number)
VALUES (#created_by_userid, #project_id)
if I were just inserting 2 values.
If inserting many values I would do SELECT and not VALUES.
If I were inserting maybe more that 1 row of values:
INSERT INTO project_member(userid, project_number)
SELECT created_by_userid, project_number FROM project
WHERE created_by_userid = #created_by_userid
Im just guessing since that is about line 46
Also, what sacse said about IF (#save_id IS NULL)
maybe there is an answer in there someplace

IF EXISTS (SELECT) in SQL Server not working as expected

I have a code like this:
IF EXISTS (SELECT * FROM table WHERE id = #id)
BEGIN
UPDATE table
SET stock = stock + #stock
WHERE id = #id
END
ELSE
BEGIN
INSERT INTO [table] ([id], [name], [stock])
VALUES (#id, #name, #stock)
END
But, this code isn't working and I am unable to find the root cause for the same. Can someone please help me?
I do not see any error in your code, I tried to replicate the process and it is working fine for me. Can you tell me what is the error you are facing exactly.
The following is the code I tried to replicate your scenario:
CREATE TABLE stocks (
id INT
,NAME VARCHAR(100)
,stock BIGINT
)
CREATE PROCEDURE InsertStocks #id INT
,#name VARCHAR(100)
,#stock BIGINT
AS
BEGIN
IF EXISTS (
SELECT *
FROM stocks
WHERE id = #id
)
BEGIN
UPDATE stocks
SET stock = stock + #stock
WHERE id = #id
END
ELSE
BEGIN
INSERT INTO stocks (
[id]
,[name]
,[stock]
)
VALUES (
#id
,#name
,#stock
)
END
END
INSERT INTO stocks
VALUES (
1
,'abc'
,200
)
INSERT INTO stocks
VALUES (
2
,'abc'
,300
)
INSERT INTO stocks
VALUES (
3
,'abc'
,500
)
EXEC Insertstocks 1
,'abc'
,700
This is updated successfully in my case.
table is a reserved keyword. so I guess you have a trivial syntax error: Incorrect syntax near the keyword 'table'. Wrap it with [], as you already did for INSERT statement
IF EXISTS (
SELECT * FROM [table] WHERE id = #id)
BEGIN
UPDATE [table] SET stock = stock + #stock
WHERE id = #id
END
ELSE
BEGIN
INSERT INTO [table] ([id]
,[name]
,[stock])
VALUES
(
#id,#name,#stock
)
END
Your code and syntax is correct. Let's see a sample example:
if EXISTS(select * from dbo.tbName where Id=1)
BEGIN
print 1
END
ELSE
BEGIN
print 2
END

SQL SERVER: Altering service broker stored procedures

I cannot alter the service broker stored procedure, when I update the stored procedure it does not show any error and successfully gets updated but the changes does not come into affect.
Is it because I need to stop the queue of the service broker on both databases before the changes could come into affect?
Note: the service broker stored procedures produce and read xmls.
INCLUDING THE STORE PROCEDURE
ALTER PROCEDURE [dbo].[ServiceBroker_AtTarget_FromSLICJobEstimateDetailsNewLineAddedBySupplier]
#XML XML(SLICMessageSchema)
AS
BEGIN
-- extract data :
DECLARE
#LogNo INT,
#QuoteReference INT,
#JobEstimatesDetailID INT,
#UserName NVARCHAR(50),
#Description NVARCHAR(MAX),
#UnitValue DECIMAL(18,2),
#Quantity DECIMAL(18,2),
#LineTotal DECIMAL(18,2),
#QuoteTotal DECIMAL(18,2),
#tsCreated DATETIME
SELECT #QuoteReference = #XML.value('data(//FromSLIC/FromSLICJobEstimateDetailsNewLineAddedBySupplier/#QuoteReference)[1]', 'int'),
#JobEstimatesDetailID = #XML.value('data(//FromSLIC/FromSLICJobEstimateDetailsNewLineAddedBySupplier/#JobEstimatesDetailID)[1]', 'int'),
#UserName = #XML.value('data(//FromSLIC/FromSLICJobEstimateDetailsNewLineAddedBySupplier/#UserName)[1]', 'nvarchar(50)'),
#Description = #XML.value('data(//FromSLIC/FromSLICJobEstimateDetailsNewLineAddedBySupplier/#Description)[1]', 'nvarchar(max)'),
#UnitValue = #XML.value('data(//FromSLIC/FromSLICJobEstimateDetailsNewLineAddedBySupplier/#UnitValue)[1]', 'decimal(18,2)'),
#Quantity = #XML.value('data(//FromSLIC/FromSLICJobEstimateDetailsNewLineAddedBySupplier/#Quantity)[1]', 'decimal(18,2)'),
#tsCreated = #XML.value('data(//FromSLIC/FromSLICJobEstimateDetailsNewLineAddedBySupplier/#tsCreated)[1]', 'datetime')
SET #LogNo = (SELECT mlq.logno FROM fsgmgtservices.dbo.maintlogquotes mlq WHERE mlq.quoteno = #QuoteReference)
INSERT INTO fsgcentraldata.dbo.[tblSLICGeneratedEvents]
(EventNameID, tsCreated, CreatedBy, IsAcknowledged, JobNumber, ContractorID)
SELECT 9, #tsCreated, #UserName, 0, #LogNo, je.contractorid
FROM [slic3.0].dbo.JobEstimates je WHERE je.legacyreference = CAST(#quotereference AS varchar(50))
SET #LineTotal = (#UnitValue * #Quantity) // IF I CHANGE IT TO ((#UnitValue * 2)) FOR EXMPL
INSERT INTO fsgmgtservices.dbo.maintlogquotedetails
(quoteno, details, quantity, rate, amount, [date], slicreference)
SELECT #QuoteReference, #description, #quantity, #UnitValue, #LineTotal, #tscreated, #JobEstimatesDetailID
SET #QuoteTotal = (SELECT SUM(mlqd.amount) FROM fsgmgtservices.dbo.maintlogquotedetails mlqd
WHERE mlqd.quoteno = #QuoteReference)
UPDATE fsgmgtservices.dbo.maintlogquotes SET amount = #QuoteTotal WHERE quoteno = #QuoteReference
INSERT INTO [fsgmgtservices].[dbo].maintlognotes
(logno, [date], [user], [note], transferredfromslic)
SELECT #LogNo, #tsCreated, #UserName, 'Quote ' + CAST(#QuoteReference AS varchar(20)) + ', new lines added by supplier in SLIC By ' + #UserName , 0
END
Changing an activated stored procedure does not kill any running instance. Most likely your old code is still running in a loop and will continue to run until it exits the loop or you kill it.

How Can i Create procedure to forbid duplicated email?

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.

Trigger on delete or update that captures the sender and the command

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