How to create stored procedure in SQL Server 2008? - sql

I'm new to stored procedures world and in one of my projects I'm trying to implement stored procedure for the search process. I'm not sure if everything I created is correct. Also I'm wondering if this code has any leaks or vulnerability for SQL injection. Here is example of my stored procedure:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Search_Dictionary]
#FilterBy INT = NULL,
#Name VARCHAR(50) = NULL,
#Code CHAR(2) = NULL
AS
BEGIN
SET NOCOUNT ON;
SELECT RecID, Status, Code, Name
FROM Dictionary
WHERE
(#FilterBy = 1 AND Name LIKE '%'+#Name+'%')
OR (#FilterBy = 2 AND Code = #Code)
OR (#FilterBy = 3 AND #Name IS NULL AND #Code IS NULL);
END
Here is example on how I call this procedure:
EXEC Search_Dictionary #FilterBy = 1, #Name = "Grant", #Code = NULL;
I just want to prevent if for example filter by is 2 that should search query by Code column returns any result if user pass word Grant. In that case should return 0 records. Also if anyone have any suggestions on how to improve the code please let me know. Thank you.

Related

Query saved in table to run in different query's where clause

I have a table that have a list of "Reports" or "Correspondence Letters" (html files). This list will appear in a dropdown in a website. Some of these items will need a "check" to see if they are allowed to be added to the dropdown.
An example of how this table (I removed columns that was not necessary to display):
In this table there is a column "Cor_PolNeedCheck_ToShow". This value links to a different table where the query for that file is stored.
From here I need to create a query that will build the actual list that will be displayed. But in order to do that I need to run the query that is in the second table to perform the check. I've created the following query to do this and it brings back the expected results:
DECLARE #retvalue INT
DECLARE #Paramater NVARCHAR(20) = '241215'
DECLARE #Cor_GroupCde NVARCHAR(10) = 248
DECLARE #Statement NVARCHAR(500);
SELECT #Statement = (SELECT Lookup_Query + #Paramater FROM [dbo].[Ref_Lookup]
WHERE Lookup_ID = (Select Cor_PolNeedCheck_ToShow FROM dbo.Ref_Correspondence WHERE Cor_Group_Cde = #Cor_GroupCde));
EXEC #retvalue = sp_executesql #Statement;
PRINT #retvalue
This value needs to be passed into a query again to verify each record to show or not to show. This is the query that will run to show the items (I have added the #retvalue of the above in the query just to show what it needs to do). This query is in a stored proc where the #Paramater will be passed (above) from the application and then to be used as needed for the below (as above query needs to fit into this one).
SELECT Cor_Group_Cde, Cor_Desc
FROM Ref_Correspondence
WHERE Cor_Show = 'Y' AND Cor_Prod_List Like '%#' + #ProdID + '#%'
AND (Cor_PolNeedCheck_ToShow IS NULL OR --#retValue > 0)
The problem I'm facing is that I need to get the #retValue into the where clause.
I have though of a stored proc, but a stored proc cannot be called in a where clause. I then though of a user defined function, but the problem there is that you cannot call a stored proc ("sp_executesql") in a function.
Due to company standards I cannot do this within the application either. Is there a way around this or is there a way to do this that I maybe missed with the above?
-------------------- EDIT ---------------------
The function I created looks like this:
USE [DBName]
GO
/****** Object: UserDefinedFunction [dbo].[ufn_CorrespondenceCheckResult] Script Date: 4/11/2019 5:35:04 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[ufn_CorrespondenceCheckResult]
(
#Paramater nvarchar(20),
#Cor_GroupCde nvarchar(10)
)
RETURNS int
AS
BEGIN
DECLARE #Statement nvarchar(MAX);
DECLARE #Return int;
set #Return = 0;
SELECT #Statement = (SELECT Lookup_Query + #Paramater FROM [dbo].[Ref_Lookup]
WHERE Lookup_ID = (Select Cor_PolNeedCheck_ToShow FROM dbo.Ref_Correspondence WHERE Cor_Group_Cde = #Cor_GroupCde));
EXEC #Return = sp_executesql #Statement;
return #Return;
END
Running the above function in my script gives me an error of "Only functions and some extended stored procedures can be executed from within a function.":
SELECT Cor_Group_Cde, Cor_Desc
FROM Ref_Correspondence
WHERE Cor_Show = 'Y' AND Cor_Prod_List Like '%#' + #ProdID + '#%'
AND (Cor_PolNeedCheck_ToShow IS NULL OR ((SELECT [dbo].[ufn_CorrespondenceCheckResult] (#Paramater,#Cor_GroupCde)) > 0))
It would be better to convert your Stored Procedure into a Function, if possible. Then you can use function in WHERE clause.
If you can't convert it into the function then better to execute the SP and store the full result in a Variable. Now you can use This table in WHERE clause.
You should store the result of the Stored Procedure in a variable in then use that in your next statement's condition. You can use an OUTPUT parameter to return the value of from the Stored Procedure.
DECLARE #count INT
EXEC FindProductByModel --CREATE a stored procedure FindProductByModel instead of a function
#Paramater = '241215',
#Cor_GroupCde = '248',
#retvalue= #count OUTPUT --#retval is an output paramater of your stored procedure
SELECT Cor_Group_Cde, Cor_Desc
FROM Ref_Correspondence
WHERE Cor_Show = 'Y' AND Cor_Prod_List Like '%#' + #ProdID + '#%'
AND (Cor_PolNeedCheck_ToShow IS NULL OR #count>0)

How to assign value in stored procedure variable when executing it?

This is my SQL code
CREATE PROC sp_procedure
(#Name VARCHAR(50),
#Stock numeric)
AS
DECLARE #Code CHAR(4)
BEGIN
UPDATE tbProcedure
SET Name = #Name, Stock = #Stock
WHERE Code = #Code
SELECT * FROM tbProcedure
END
Then I execute the code like this
EXEC sp_procedure 'Name',15,2
Then I got error result saying too many argument specified.
I also tried this
EXEC sp_procedure 'Name',15
It doesn't return an error, but 0 rows affected.
I want to assign #Code value when I execute the stored procedure, is it even possible to do that ?
EDIT:
Sorry, it's actually a CHAR(4), not INT
Again sorry, I just copy paste all code without looking at it first, above is the actual code, I am very sorry for the confuse...
It looks like you are providing the parameters in a different order than you have declared them. Choice is declared before Name but you are providing Name first when executing the procedure. Also, don't you want your update statement to say "code = #choice"? The local variable is undefined and not needed.
For Microsoft SQL Server
For your problem:
(don't use sp prefix) and (#code is not a parameter so we cannot pass value, it is local variable)
If you are having some problems with IF then, make #code as parameter but pass null value when needed and make that null check in procedure.
See below to assign values:
USE [databasename]
GO
DECLARE #return_value int
EXEC #return_value = <procedurename>
#stringvariable = N'<stringvalue>',
#Flag = <integervalue>
SELECT 'Return Value' = #return_value (return value if any)
GO
I have come to a conclusion that its impossible to combine branching stored procedure if one of the branch do not use all the parameters.
And because of that I have write 2 stored procedures, below is my full code :
For insert procedure: [this is the procedure that using a variable]
CREATE PROC InsProcedure
(#Name VARCHAR(50),
#Stock numeric)
AS
DECLARE #CODE INT
DECLARE #CODE2 CHAR(4)
BEGIN
// Creating custom auto number
SET #CODE = 0
SELECT #CODE = ISNULL(MAX(CAST(KodeBarang AS INT)), 0)
FROM tbProcedure
SET #CODE2 = #CODE + 1
SET #CODE2 = REPLICATE('0', 4 - LEN(#CODE2)) + #CODE2
// End Custom auto number
INSERT INTO tbProcedure VALUES(#CODE2, #Name, #Stock)
SELECT * FROM tbProcedure
END
For update, delete, and show procedure:
CREATE PROC OtherProcedure
(#choice int, // this is for branching option later
#Code CHAR(4),
#Name VARCHAR(50),
#Stock numeric)
AS
IF #choice = 1
BEGIN
UPDATE tbProcedure
SET Name = #Name, Stock = #Stock
WHERE Code = #Code
SELECT * FROM tbProcedure
END
ELSE IF #choice = 2
DELETE FROM tbProcedure
WHERE KodeBarang = #Code
ELSE
SELECT * FROM tbProcedure
and use the procedures like this :
InsProcedure 'Laptop', 5
Result:
00001, Laptop, 5
Branch 1 [Update]
OtherProcedure 1, 'Laptops', 10, 00001
Result:
Before : 00001, Laptop, 5
After : 00001, Laptops, 10
Branch 2 [Delete]
OtherProcedure 2, '', 0, 00001 // Delete record where Code is '00001'
Branch 3 [Show]
OtherProcedure 3, '', 0, 0 // You can also use any number besides 3
First of all, your variable #Stock doesn't return decimal because it's INT variable, you might try float or something else. It's the reason why it shows an error if you give it "15,2"
WHERE Code = #Code
And 0 rows affected was caused because you didn't set that variable properly.
You have to assign a valid value to it.

Scope_Identity not being returned as expected

Using entity Framework, vb and sql server.
I have a stored procedure (shown below) to insert a new record and return the new identity of the record concerned (the id column is a properly defined identity column). The stored procedure is imported into my entity data model and called as a function, with the expected result being the identity of the new record. However I always get 0 returned instead.
If I execute the stored procedure in ssms I get the result I'm expecting in the results window and also a separate result with the value of 0 (which is clearly what is being returned to my mapped stored procedure).
Either I have an error in my stored procedure, or I'm doing something wrong with the way that I call the function (also shown below). I'd be really grateful for any suggestions that you might have to offer.
The stored procedure:
ALTER PROCEDURE [Finances].[CreatePurchaseInvoicePayment]
-- Add the parameters for the stored procedure here
#PurchaseInvoiceId int = NULL,
#SupplierId int = NULL,
#PurchaseInvoicePaymentDate date = NULL,
#Amount money = NULL,
#PaymentType int = NULL,
#ChequeNumber nchar(10) = NULL,
#BankAccountId int = NULL,
#purchaseInvoiceCreditNoteId int = NULL,
#ConversionFactor numeric(4,2) = NULL,
#ModifiedDate date = NULL,
#id int = NULL OUTPUT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
INSERT INTO Finances.PurchaseInvoicePayments
VALUES
(
#PurchaseInvoiceId,
#SupplierId,
#PurchaseInvoicePaymentDate,
#Amount,
#PaymentType,
#ChequeNumber,
#BankAccountId,
#purchaseInvoiceCreditNoteId,
#ConversionFactor,
#ModifiedDate
)
SET #id = SCOPE_IDENTITY()
END
which is being called like this:
Try
pipId = CInt(te.CreatePurchaseInvoicePayment(pip.PurchaseInvoiceId, pip.SupplierId, pip.PurchaseInvoicePaymentDate, pip.Amount, pip.PaymentType, pip.ChequeNumber, pip.BankAccountId, pip.PurchaseInvoiceCreditNoteId, pip.ConversionFactor, pip.ModifiedDate,nothing).FirstOrDefault)
Catch ex As Exception
As I say if anyone could point me in the right direction I'd be most grateful.
I believe function expects an actual resultset from the SP. In this case you don't need an output parameter, just add at the end of SP:
SELECT SCOPE_IDENTITY()
and the function should read it correctly.

"Subsequent parameters" error in SSRS?

I'm getting a strange error in SSRS, in a report (which gets put into a sproc) with many drop-down parameters:
Query execution failed for dataset 'DataSet1'.
Must pass parameter number 3 and subsequent parameters as '#name = value'. After the form '#name = value' has been used, all subsequent parameters must be passed in the form '#name = value'
I'm lost on what's going on here - what is meant by #name = value .
I searched online, someone mentioned that you should alter the stored-procedure?
Here is how the top half of my stored-proc looks:
USE [FederatedSample]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[prc_RPT_Select_BI_Completes_Data_View_2]
#FromDate DATETIME,
#ToDate DATETIME,
#AccountIDs VARCHAR(max) = null,
#ClientIDs VARCHAR(max) = null,
#SupplierIDs VARCHAR(max) = null,
#CompleteType INT = NULL,
/*
* 0 - Routed
* 1 - Targeted
* 2 - Offerwall
*/
#SourceType BIT = NULL,
/*
* Works if #AccountID is not null
* (should only be used if #AccountID has a single value)
*
* 0 - Owned by #AccountID
* 1 - External (not owned by #AccountID)
*/
#SurveyStatus INT = NULL,
/*
* NULL - All Surveys
* 0 - Completes Approved Surveys
* 1 - Invoiced Surveys
*/
#IsSupplierUser BIT = 0
/*
* used to decide whether to display FEDSurveyName or SupplierSurveyName
*/
AS
BEGIN
SET NOCOUNT ON
DECLARE #SQL NVARCHAR(MAX) = N'',
#Params NVARCHAR(MAX)
IF #AccountIDs is not null
BEGIN
SET #SQL += N'DECLARE #AccountIDs VARCHAR(MAX) = #pAccountIDs; '
END
IF #ClientIDs is not null
BEGIN
SET #SQL += N'DECLARE #ClientIDs VARCHAR(MAX) = #pClientIDs; '
END
IF #SupplierIDs is not null
BEGIN
SET #SQL += N'DECLARE #SupplierIDs VARCHAR(MAX) = #pSupplierIDs; '
END
SET #SQL += N'
SELECT bi.SupplierID as ''Supplier ID''
,bi.SupplierName as ''Supplier Name''
,bi.PID as ''PID''
,bi.RespondentID as ''Respondent ID''
,lk_slt.Name as ''Entry Link Type''
,ts.SurveyNumber as ''Initial Survey ID'''
And later in the stored proc. it does stuff like this to split strings:
IF #AccountIDs is not null
BEGIN
SET #SQL += CHAR(13) + CHAR(9)
SET #SQL += N' and bi.AccountID in (SELECT CAST(val as INT) FROM dbo.Split(#AccountIDs, '','
When invoking a stored procedure, you either can pass the parameters by position (not a good idea) or by Name (a better approach IMHO).
EXEC dbo.MyStoredProcedure '12/31/2012', 1; -- Not a great way to pass parameters
EXEC dbo.MyStoredProcedure #AsOfDate = '12/31/2012', #AccountID = 1; -- A better way
From the error message you are receiving, I suspect that SSRS is using the second approach and is running into an issue with the third parameter being provided to the stored procedure.
Without more information to go off of it is difficult to provide you with an exact explanation for the error (the stored procedure would perhaps help), an educated guess is that the way the parameters are being provided for Account IDs, Client IDs and Supplier IDs isn't quite correct. Specifically, I think the problem might be that you are providing multiple identifiers delimited by a comma.
You might try passing a single Account ID, Client ID and Supplier ID to see if you still receive the error. I would also try to look at the stored procedure (or talk to the DBA \ Developer who wrote it) to ascertain the intended usage of the stored procedure.
I got a similar message when passing a comma instead of a full stop for a decimal value in one of the parameters of a stored procedure.
Here is a simplified example of what happened.
The following command string was erroneously generated with the value of #param2 with a comma instead of a full stop, causing a misunderstanding of the number of parameters.
EXEC myStoredProc #param1 = 1, #param2 = 0,5 ,#param3 = 'something'

SQL Stored Procedure to return results with multiple parameters

I want to create a stored procedure that returns the results of a search for "similar records". The stored procedure i currently have is as follows
CREATE PRODECURE [dbo].[viewSimilarRecords]
#recordType varchar(25),
#recordSource varchar(25)
AS
SELECT * FROM myTableName
WHERE
(recordtype = #recordType) AND
(recordsource = #recordSource)
GO
The problem i'm having is that when it executes i get a return value 0 and the resulting rows do not show up (SQL Server Management Studio).
I can confirm i'm passing the correct values in the params and that multiple records do exist.
This is the execute Statement when it's ran
USE [databasename]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[ViewSimilarRecords]
#recordType = N'Error',
#recordSource = N'Local'
SELECT 'Return Value' = #return_value
GO
Without more information to go on, I'm just guessing but perhaps no data matches your parameters. the procedure is viewSimilarRecords and not viewExactmatchingRecords. The way it is coded you must have an exact match for every parameter. Possibly you need to try something like this:
CREATE PROCEDURE [dbo].[viewSimilarRecords]
#recordType varchar(25),
#recordSource varchar(25)
AS
SELECT * FROM myTableName
WHERE
(recordtype =#recordType OR #recordType IS NULL) AND --<<change to OR??
(recordsource=#recordSource OR #recordSource IS NULL)
--^^^^^^^^^^^^^^^^^^^^^^^^
GO
you could take a look at this: Dynamic Search Conditions in T-SQL by Erland Sommarskog
Check all of the little (obviously, it could never be that...) things...
1) Verify the procedure exists. In your create statement, you mis-spelled p-r-o-*c-e-*d-u-r-e
2) When you execute, you're enforcing unicode (N') on non-unicode variables.
#recordType = N'Error', #recordSource = N'Local'
Try this instead:
#recordType = 'Error', #recordSource = 'Local'
3) Instantiate the parameters and run just this part of the procedure directly (highlight and press F5) to make sure you get results.
ECLARE #recordType varchar(25)
ECLARE #recordSource varchar(25)
SET #recordType = 'Error'
SET #recordSource = 'Local'
SELECT * FROM myTableName
WHERE
(recordtype = #recordType) AND
(recordsource = #recordSource)
4) Run this directly, all by itself (if item 3 above was successful to verify that you're in the right database:
EXEC [dbo].[ViewSimilarRecords] 'Error','Local'