stored procedure executes correctly from management studio, but not in production - sql

I have a stored procedure that works correctly when I execute the stored procedure from SQL Server Management Studio. Unfortunately, it doesn't behave the the same way on the production server. On an insert statement, it is only inserting some of the values and the rest are NULL. The NULL values are coming from user defined scalar function calls (which also work correctly when executed from Management Studio). Has anyone run into anything similar? I was thinking it might be a permissions issue, but I connected to the database through Management Studio with the production connection credentials and saw the same behavior. I'm a C# developer that normally works with ORMs, so I'm definitely no SQL expert. Thanks in advance, guys.
Here is the code:
BEGIN
DECLARE #UserExists int
SET #UserExists = 0
SELECT #UserExists = COUNT(*) FROM UserPass WHERE UserId = #UserID AND PortalID = #PORTALID
--If the Action is add and a User Exists change the Action to EDT (Update)
IF #Action = 'ADD' AND #UserExists > 0
SET #Action = 'EDT'
--Get All Of the Properties for this User
DECLARE #EMAIL nvarchar(255)
DECLARE #FIRSTNAME nvarchar(50)
DECLARE #LASTNAME nvarchar(50)
DECLARE #GENDER char(1)
DECLARE #BIRTHDATE smalldatetime
DECLARE #ADDRESS nvarchar(50)
DECLARE #CITY nvarchar(50)
DECLARE #STATE nchar(2)
DECLARE #COUNTRY nvarchar(50)
DECLARE #POSTALCODE nvarchar(10)
DECLARE #TELEPHONE nvarchar(20)
DECLARE #CELL nvarchar(20)
DECLARE #EMAILPERMISSION bit
DECLARE #TEXTPERMISSION bit
DECLARE #UPDATEDIRECTION nvarchar(3)
BEGIN TRY
SELECT #BIRTHDATE = CAST(dbo.GetPropertyValue(#PORTALID,#USERID,'Birthdate') AS SmallDatetime)
END TRY
BEGIN CATCH
SELECT #BIRTHDATE = NULL
END CATCH
SELECT #EMAIL = Email,
#FIRSTNAME = dbo.Proper(Firstname),
#LASTNAME = dbo.Proper(Lastname),
#GENDER = dbo.GetPropertyValue(#PORTALID,#USERID,'Gender'),
#ADDRESS = dbo.GetPropertyValue(#PORTALID,#USERID,'Street'),
#CITY = dbo.Proper(dbo.GetPropertyValue(#PORTALID,#USERID,'City')),
#STATE = Upper(dbo.GetState(dbo.GetPropertyValue(#PORTALID,#USERID,'Region'))),
#COUNTRY = dbo.GetPropertyValue(#PORTALID,#USERID,'Country'),
#POSTALCODE = dbo.GetPropertyValue(#PORTALID,#USERID,'Postalcode'),
#TELEPHONE = dbo.STRFILTER(dbo.GetPropertyValue(#PORTALID,#USERID,'Telephone'),'0,1,2,3,4,5,6,7,8,9'),
#CELL = dbo.STRFILTER(dbo.GetPropertyValue(#PORTALID,#USERID,'Cell'),'0,1,2,3,4,5,6,7,8,9'),
#EMAILPERMISSION = dbo.GetPropertyValue(#PORTALID,#USERID,'eNewsLetter'),
#TEXTPERMISSION = dbo.GetPropertyValue(#PORTALID,#USERID,'TextPermission')
FROM Users
WHERE UserId = #USERID
-- Insert new user
IF #Action = 'ADD'
BEGIN
INSERT INTO UserPass
(UserID, Portalid, CreatedDate, Username, UserPass.Password, email, firstname, lastname, gender, birthdate, UserPass.address, city, UserPass.state, country, postalcode, telephone, cell, emailpermission, textpermission, UpdateDirection)
VALUES
(#UserID, #PORTALID, #CREATEDDATE, #Username, #Password, #EMAIL, #FIRSTNAME, #LASTNAME,#GENDER, #BIRTHDATE, #ADDRESS, #CITY, #STATE, #COUNTRY, #POSTALCODE, #TELEPHONE, #CELL, #EMAILPERMISSION, #TEXTPERMISSION, 'OUT')
END
#PORTALID and #USERID are passed to the stored procedure as parameters, and those values are actually saving in the insert. The columns that aren't updating are the ones that call the GetPropertyValue function for the value. This is only on one database server (I am not connecting to a dev database through Management studio, I am connecting directly to the production database). When I execute the stored procedure from Management Studio, it's perfect. When the trigger on the table calls the sproc, the GetPropertyValue function fails.

Get SQL Profiler on it and then copy & paste & execute the statements from that in query analyser.
It's likely that your production is producing subtlely different code or is injecting different param values than the ones you expect and this will catch exactly what is happening.

While it's impossible to see what is happening without table structures, sprocs and functions my thoughts would be to compare the table structures, defaults, identity columns, etc. in PROD and DEV.

That says to me something is funny in your application code. I would check your C# logic and make sure you are using the right function call on the command object. It might help to post your code.

As Nissan Fan says, you haven't provided nearly enough information. That said, one possibility is that you're on SQL Server 2000 and are encountering an old bug. If you want a useful answer, though, ask a useful question.

Related

I want to write the code I created with the 'Stored procedure' as a function

CREATE PROC add_person
(
#id tinyint,
#name nvarchar(max),
#surname nvarchar(max),
#salary int,
#job nvarchar(max)
)
AS
BEGIN
INSERT INTO information
VALUES(#id,#name,#surname,#salary,#job)
END
I want to write this code as a function. But the concept of "return" confuses me. That's why I couldn't.
I tried to write the code above as a function. This code came out.
CREATE FUNCTION add_person
(
#id tinyint,
#name nvarchar(max),
#surname nvarchar(max),
#salary int,
#job nvarchar(max)
)
RETURNS TABLE
AS
BEGIN
RETURN INSERT INTO information -- not work
VALUES(#id,#name,#surname,#salary,#job)
END
If you want to return the newly created table, you can use the stored procedure to do that. If you're using SQL Server, the code would be:
BEGIN
INSERT INTO information -- not work
VALUES(#id,#name,#surname,#salary,#job);
SELECT * FROM information WHERE id = ##identity; -- this is the primary key just created.
END
Functions are much more limited in their functionality than are stored procedures.
Although insert is allowed, it is only allowed in local variables. As the documentation says:
INSERT, UPDATE, and DELETE statements modifying local table variables.
On the other hand, a stored procedure can return a value. Normally, this is a status code, where 0 means everything succeeded, and any other value means that the process failed.

How to pass value to stored procedure with spatial/geography data type using SQL query

I'm a student and after 2H searching answer I'm hopping that someone can help me here.
I created a stored procedure that expects a name, address and geography location then adds a new branch to the Branches table. I'm trying to pass a geography value using a new query, but I keep getting a syntax error.
Stored procedure :
create procedure AddBranch
#Name nvarchar(50),
#Address nvarchar(100),
#GeographicLocation geography
as
begin
SET NOCOUNT ON
insert into Branches (Name, Address, GeographicLocation)
values (#Name, #Address, #GeographicLocation)
select BranchID
from Branches
where BranchID = SCOPE_IDENTITY()
end
Query:
exec AddBranch
#Name = 'Some Name',
#Address = 'Some Address',
#GeographicLocation = geography::Point(47.65100, -122.34900, 4326)
Error:
Incorrect syntax near'::'
Is there a way to pass geography data to a stored procedure?
In addition to enclosing the arguments in quotes, you need to assign the method result to a local variable in order to pass the value as a parameter in T-SQL:
DECLARE #geographyPoint geography = geography::Point('47.65100', '-122.34900', '4326');
exec AddBranch
#Name = 'Some Name',
#Address = 'Some Address',
#GeographicLocation = #geographyPoint;
as a sidenote:
create procedure dbo.AddBranch --always specify schema
#Name nvarchar(50),
#Address nvarchar(100),
#GeographicLocation geography
as
begin
SET NOCOUNT ON
SET XACT_ABORT ON --should be in every data modification SP
insert into dbo.Branches (Name, Address, GeographicLocation) --schema!
output inserted.BranchID --this
values (#Name, #Address, #GeographicLocation)
select SCOPE_IDENTITY() BranchID --or this
--absolutely no need in another read operation from persistent table
end
Put the values into quotes like this
exec AddBranch
#Name = 'Some Name',#Address = 'Some Address',
#GeographicLocation = geography::Point('47.65100', '-122.34900', '4326')
go
Although this might not work depending on how this custom Geography type expects its values, it will solve the syntax error.

Stored Proc returns 2 return values

I have a stored proc that first checks if an entry exists and if so updates it then returns the row ID, if not it inserts a new record then returns the row ID.
When executing the stored proc I am given 2 return values, one with the field '#PersonID' and the other with 'Return Value'. I'm pretty sure this is happening because of the SELECT statement that is used in the IF EXISTS, however, I'm unable to figure a way to suppress it and I was hoping someone could help.
ALTER PROCEDURE [dbo].[InsertPerson]
-- Add the parameters for the stored procedure here
#FirstName nvarchar(50),
#LastName nvarchar(50),
#PersonID int OUT
AS
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
IF( EXISTS (SELECT PersonID FROM People
WHERE FirstName = #FirstName AND LastName = #LastName))
BEGIN
SET #PersonID = (SELECT PersonID
FROM People
WHERE FirstName = #FirstName
AND LastName = #LastName)
UPDATE People
SET
FirstName = #FirstName,
LastName = #LastName
WHERE PersonID = #PersonID
END
ELSE
BEGIN
INSERT INTO People (FirstName, LastName) VALUES(#FirstName, #LastName)
SET #PersonID = SCOPE_IDENTITY()
SELECT #PersonID
END
Thanks for the quick responses. I had accidently posted some incorrect code, the actual stored proc doesn't have SELECT #PersonID at the end. However, I think I have incorrectly identified the stored proc as the root cause of the issue I'm working on and as pointed out in the responses everything is working as expected.
Thanks again for the help

Lock Stored Procedure in SQL

I have a stored procedure which inserts info into multiple tables and gets the IDs by SCOPE_IDENTITY(). I would like to prevent multiple users from executing it at the same time, so that my IDs don't get mixed up.
How do I lock it? I have read about sp_getapplock and sp_releaselock, but there is no clear explanation how to use it. Below I put my procedure.
create procedure AddPerson(
#Name nvarchar(255),
#LastName nvarchar(255),
#City nvarchar(255),
#Address nvarchar(255)
)
as
BEGIN TRY
BEGIN TRANSACTION
insert into Location(Address, City)
values(#Address, #City)
declare #LocationID int
set #LocationID = SCOPE_IDENTITY()
insert into PersonalInfo(Name, LastName)
values (#Name, #LastName)
declare #PersonInfoID int
set #PersonInfoID = SCOPE_IDENTITY()
insert into Teacher
values(#LocationID, #PersonInfoID)
COMMIT
END TRY
BEGIN CATCH
ROLLBACK
END CATCH
No locking of any kind needed - this behavior you're trying to accomplish is already in place implicitly.
SCOPE_IDENTITY() returns the new ID in the scope of each transaction - so if 10 users are running this simultaneously, each will get their own, separate ID back from SCOPE_IDENTITY

Stored Procedure Cross Table ID Input

I'm trying to insert other table's IDs (Company and Bank) into the uBankID and uCompanyID of the EndUser table and the BankID of the Company table on INSERT.
Whatever way I do this, the required fields aren't being populated, what am I doing wrong? I had a look at an inline select statement at the ID to try and grab it but couldn't fathom it and it wouldn't compile.
The variables are all present and correct in the backend and are being parsed through, all but these IDs, as nothing is going wrong with the C# I'm thinking there's something amiss with my SQL, especially as I'm fairly new to stored procedures.
Any help would be greatly appreciated.
Code (slimmed down):
CREATE PROCEDURE [ProcedureInsert]
#Title nvarchar(10),
#FirstName nvarchar(50),
#LastName nvarchar(50),
#Organisation nvarchar(50),
#Address nvarchar(50),
#uBankID int,
#uCompanyID int,
#BankID int,
#SortCode int,
#AccountNumber nvarchar(50),
#AccNameHolder nvarchar(50),
#cId int output,
#bId int output,
#euId int output
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO [Bank](SortCode, AccountNumber, AccNameHolder)
VALUES(#SortCode, #AccountNumber, #AccNameHolder)
SET #bId = SCOPE_IDENTITY();
INSERT INTO [Company](Organisation, Address, BankID)
VALUES(#Organisation, #Address, #bId)
SET #cId = SCOPE_IDENTITY();
INSERT INTO [EndUser](Title, FirstName, LastName, uBankID, uCompanyID)
VALUES(#Title, #FirstName, #LastName, #uBankID, #cId)
SET #euId = SCOPE_IDENTITY();
END
You need to declare the variables. And Tab Alleman is right, get rid of the unused parameters.
DECLARE #cId int;
DECLARE #bId int;
DECLARE #euId int;
INSERT INTO [BAD](SortCode,AccountNumber,AccNameHolder)
VALUES('1234','a234','Test Name')
SET #bId=SCOPE_IDENTITY();
INSERT INTO [Company](Organisation,Address1, Address2,City,County,PostCode,Telephone,BankID)
VALUES('AnOrganisation','addressesss','Address2','City','County','PostCode','0123one', #bId)
SET #cId=SCOPE_IDENTITY();
INSERT INTO [EndUser](Title,FirstName,LastName,Email,uBankID,uCompanyID)
VALUES('Sitle','Fiame','astName','vv#Email',#bId,#cId)
SET #euId=SCOPE_IDENTITY();
EDIT
Remove those parameters if they're not being used, but they weren't in the sample code, else leave them, obviously.
Also, I used single quotes to dump in the data into the table rather than variables, if it's not working then there's something wrong with the bank end code.