Stored Procedure take either or variables? - sql-server-2005

I'm working in sql server 2005 here and I wanted to know if there was a way to make a stored procedure take variable a or variable b for its parameters.
Right now if I declare A and B it requires both A and B. Possible to make it take A or B instead? So that if the other one doesn't have a value it uses the other?
ex:
#ID VARCHAR(255)
#MAKE VARCHAR(255)
AS
BEGIN
SET NOCOUNT ON
SELECT *
FROM CARS
WHERE ID = #ID OR MAKE =#MAKE
Thanks!

create procedure MyProcedure
(
#ID VARCHAR(255) = NULL,
#MAKE VARCHAR(255) = NULL
)
AS
SET NOCOUNT ON
SELECT *
FROM CARS
WHERE
(#ID IS NOT NULL AND ID = #ID)
OR
(#MAKE IS NOT NULL AND MAKE =#MAKE)

IF ID IS NULL
BEGIN
/*Code goes here*/
END
ELSE IF MAKE IS NULL
BEGIN
/*More code goes here*/
END
ELSE
BEGIN
/*Even more code goes here*/
END
I'm quite sure you can call a function using NULL.
And, also do this:
#ID VARCHAR(255) = NULL
#MAKE VARCHAR(255) = NULL
Read this: http://weblogs.asp.net/stanleygu/archive/2010/02/08/solution-5-implementing-optional-parameters-in-t-sql-stored-procedures.aspx

Stored procedures can take optional arguments.
create procedure mysp
#a varchar(255) = NULL,
#b varchar(255) = NULL
as begin
select *
from cars
where (a = #a and #a is not NULL) or
(b = #b and #b is not NULL);
end;

Related

What's better to optimize a database: use a bunch of stored procedures with different filters or use a single one with if conditions?

I'm trying to optimize my database so, I decided to change a stored procedure which has a lot of "IF CONDITIONS" to filter with different parameters.
So, I was thinking on change it and make a bunch of stored procedures with different filters and stop using the one with a lot of "IF CONDITIONS"
And just validate on my backend which stored procedure use, instead of do it in SQL Server.
This is the best way to do it or there are better ways to do this?
Example of my actual stored procedure:
CREATE PROCEDURE [dbo].[sp_GetFilters]
#Id INT,
#Name VARCHAR(50),
#LastName VARCHAR(50),
#Age INT,
#AND_MORE_PARAMETERS VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
IF #ID IS NOT NULL AND
#NAME IS NULL AND
#LASTNAME IS NULL AND
#AGE IS NULL AND
#AND_MORE_PARAMETERS IS NULL
BEGIN
SELECT *
FROM EXAMPLE_TABLE
WHERE ID = #ID
END
ELSE IF #ID IS NULL AND
#NAME IS NOT NULL AND
#LASTNAME IS NULL AND
#AGE IS NULL AND
#AND_MORE_PARAMETERS IS NULL
BEGIN
SELECT *
FROM EXAMPLE_TABLE WHERE
NAME = #NAME
END
...
and so on..
I want to change that one to a bunch of different stored procedures, each one of them with a unique filter
It is a good idea? There are better ways to optimize this stored procedure?
Thanks, for the help!
You could try one query, with parameter evaluation in the WHERE clause. I've used this approach widely with great success.
CREATE PROCEDURE dbo.sp_GetFilters
#Id INT = NULL
,#Name VARCHAR(50) = NULL
,#LastName VARCHAR(50) = NULL
,#Age INT = NULL
,#AND_MORE_PARAMETERS VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
SELECT *
FROM EXAMPLE_TABLE
WHERE 1 = 1
AND CASE WHEN #Id IS NULL THEN 1 ELSE ID END = CASE WHEN #Id IS NULL THEN 1 ELSE #Id END
AND CASE WHEN #Name IS NULL THEN '1' ELSE NAME END = CASE WHEN #Name IS NULL THEN '1' ELSE #Name END
AND CASE WHEN #Age IS NULL THEN 1 ELSE AGE END = CASE WHEN #Age IS NULL THEN 1 ELSE #Age END;
/* and so on....*/
END;

Stored procedure in SQL Server does not return a result set when called by java

I have the following stored procedure and my goal is to return a result set from it, using the query "select * from #justTmp"
create procedure spAddPerson
#ID int,
#Name nvarchar(50)
as
begin
create table #justTmp
(
num int primary key,
justName nvarchar(50)
)
if #ID in (select C.ContributorID
from Contributors C)
begin
insert into #justTmp
values (#ID, #Name)
end
select *
from #justTmp
end
And this is my java code
CallableStatement cstmt = null;
ResultSet rs = null;
cstmt=conn.prepareCall("{ call spAddPerson(?,?) }");
cstmt.setInt(1, 1);
cstmt.setString(2, "MyName");
cstmt.execute();
rs=cstmt.getResultSet();
int first=rs.getInt(1);
String second=rs.getString(2);
For some reason, whenever I run it, and the above stored procedure is called, I get an exception that says
The statement did not return a result set
when the
rs = cstmt.getResultSet()
code is executed.
Any idea how to fix this so a result set would return and not null?
Thanks in advance
Try this :
create proc spAddPerson
#ID int,
#Name nvarchar(50)
as
begin
SET NOCOUNT ON
...
There are multiple ways but try this once:
create proc spAddPerson
#ID int,
#Name nvarchar(50)
as
begin
SET NOCOUNT ON;
create table #justTmp
(
num int primary key,
justName nvarchar(50)
)
if #ID in
(
select C.ContributorID
from Contributors C
)
begin
insert into #justTmp
values(#ID,#Name)
end
select *
from #justTmp
RETURN
end
On your java code change
call spAddPerson
To
exec spAddPerson

How can I return tables with different number of parameters with procedure?

I'm going to create different temp tables depending on the #selection parameter I get, and then I want to return the table I created.
I actually wanted to do it with the function, but I got an error for variable parameter tables. The sql procedur I wrote is as follows:
ALTER PROCEDURE [dbo].[Report]
(#Id BIGINT = 55,
#selection INT)
AS
BEGIN
IF #selection=1
BEGIN
Declare #tep_table table (Id int
,Name varchar(250)
,CreateTime datetime
,UpdateTime datetime
,UpdatedBy varchar(250)
,Deleted bit
)
Insert into #tep_table
Select * from User
END
IF #selection=1
BEGIN
Declare #tep_table2 table (Id int
,CreateTime datetime
,UpdateTime datetime
,UpdatedBy varchar(250)
,Deleted bit
)
Insert into #tep_table2
Select * from Client
END
IF #selection=1
BEGIN
RETURN #tep_table
END
ELSE
BEGIN
RETURN #tep_table2
END
END
I am getting this error:
Must declare the scalar variable "#tep_table"
Personally I would turn this into three procedures to avoid the performance problems faced with multiple execution paths.
Something like this.
ALTER Procedure [dbo].[Report]
(
#Id bigint = 55 --not sure what the point of this parameter is as it wasn't used anywhere in the sample code
, #selection int
) AS
set nocount on;
IF #selection = 1
exec GetUserData;
IF #selection = 2
exec GetClientData;
GO
create procedure GetUserData
AS
set nocount on;
Select * --would prefer to use column names here instead of *
from [User];
GO
create procedure GetClientData
AS
set nocount on;
Select * --would prefer to use column names here instead of *
from Client;
GO

How can I not send Null to database while using Update

If i need to just update one column do i have to give other column previous value or i can just give give the column i need to change and not null values to update in database .. here is procedure code what can i do to this procedure so that i can just need to insert the value i want to update ...
ALTER procedure [dbo].[Customer_update]
( #Id int,
#Firstname nvarchar(40)=,
#Lastname nvarchar(40)=,
#City nvarchar(40)=null,
#Country nvarchar(40)=null,
#Phone nvarchar(20)=null
)
as
begin
update Customer set FirstName=#Firstname,LastName=#Lastname,City=#City,Country=#Country,Phone=#Phone where Id=#Id
end
You almost have it and as Alex K pointed out in the comment above, the most elegant way to handle optional updates is to allow null parameters and update what is sent over.
ALTER PROCEDURE [dbo].[Customer_update]
(#Id INT,
#Firstname NVARCHAR(40) = NULL,
#Lastname NVARCHAR(40) = NULL,
#City NVARCHAR(40) = NULL,
#Country NVARCHAR(40) = NULL,
#Phone NVARCHAR(20) = NULL)
AS
BEGIN
UPDATE Customer
SET FirstName = ISNULL(#Firstname, FirstName)...
WHERE Id = #Id
END
In order to use this in client code with nullable fields, simply omit the parameter altogether or let nulls pass through (one caveat to this is when you really need to set the field to null in which case the field should probably not be nullable. Then you can implicitly send a null over and the field will be set to the proper value)
Nullable fields allow you to omit parameters from a stored procedure call and still perform the operation. This is useful when you need make changes and do not want to impact existing applications, as long as the nullable fields are not required.
Are you asking about Insert/Update in one operation?
Some people do "upserts". I personally do not like having one operation for insert/updates. I feel the client should already know what operation should be performed, also, having one update and one insert procedure makes the procedures more transparent and easier to auto generate.
However, if that is what you were asking then you would create a procedure similar to the one below:
ALTER PROCEDURE [dbo].[Customer_update]
(#Id INT = NULL,
#Firstname NVARCHAR(40) = NULL,
#Lastname NVARCHAR(40) = NULL
#City NVARCHAR(40) = NULL
#Country NVARCHAR(40) = NULL
#Phone NVARCHAR(20) = NULL)
AS
BEGIN
IF (#Id IS NULL)
BEGIN
INSERT INTO Customer...
SET #ID = ##SCOPE_IDENTITY
END
ELSE BEGIN
UPDATE Customer
SET FirtName = ISNULL(#FirstName, FirstName)
WHERE Id = #Id
END
SELECT *
FROM Customer
WHERE Id = #Id
END
You would need to use ISNULL on each column:
ALTER procedure [dbo].[Customer_update]
( #Id int,
#Firstname nvarchar(40)=,
#Lastname nvarchar(40)=,
#City nvarchar(40)=null,
#Country nvarchar(40)=null,
#Phone nvarchar(20)=null
)
as
begin
update Customer
set FirstName=ISNULL(#Firstname,FirstName),
LastName=ISNULL(#Lastname,LastName),
City=ISNULL(#City,City),
Country=ISNULL(#Country,Country),
Phone=ISNULL(#Phone,Phone)
where Id=#Id
end

SQL Assign value to local variable take from table

This i my procedure,that determines classId and liveareaId for Animal to insert it into table
CREATE PROCEDURE insertAnimal
#name nvarchar,
#birthyear int,
#classname nvarchar,
#livearea nvarchar
AS
BEGIN
DECLARE #classid int
DECLARE #liveareaid int
SET #classid =
(SELECT Id
FROM dbo.Class
WHERE dbo.Class.Name = #classname)
SET #liveareaid =
(SELECT Id
FROM dbo.LiveArea
WHERE Name = #livearea)
INSERT INTO dbo.Animal (Name,BirthYear,ClassId,LiveAreaId) VALUES
(
#name,
#birthyear,
#classid,
#liveareaid
)
END
GO
I have a error:
Cannot insert the value NULL into column 'ClassId', table 'ZOO.dbo.Animal'; column does not allow nulls. INSERT fails.
Why ClassId is null, can you tell me why whis doesn't work.
SET #classid =
(SELECT Id
FROM dbo.Class
WHERE dbo.Class.Name=#classname)
This is because you have declared #classname as only nvarchar and have not specified a length. When length is not specified in a nvarchar variable declaration statement, the default length is 1.
Declare as:
CREATE PROCEDURE insertAnimal
#name nvarchar(10),
#birthyear int,
#classname nvarchar(10),
#livearea nvarchar(10)
...
CREATE PROCEDURE insertAnimal
#name nvarchar,
#birthyear int,
#classname nvarchar,
#livearea nvarchar
AS
BEGIN
DECLARE #classid int
DECLARE #liveareaid int
SET #classid =
(SELECT Id
FROM dbo.Class
WHERE dbo.Class.Name=#classname
AND dbo.Class.Id IS NOT NULL)
SET #liveareaid =
(SELECT Id
FROM dbo.LiveArea
WHERE Name=#livearea)
INSERT INTO dbo.Animal (Name,BirthYear,ClassId,LiveAreaId) VALUES
(
#name,
#birthyear,
#classid,
#liveareaid
)
END
GO
Can you tell us which parameteres are passing by you while calling procedure in your page/Query as well as sample data in your database?
It looks like data does not exists in your database according to your parameters in page.
Make sure #classname and #liveareaid data you are passing as a parameter, must be in database table dbo.Class and dbo.LiveArea respectively.
Try below queries first in SQL server.Does it giving any output by same parameters?
SELECT Id FROM dbo.Class WHERE dbo.Class.Name = #classname
SELECT Id FROM dbo.LiveArea WHERE Name = #livearea