As my title suggests, I have a stored procedure query where I pass in a parameter and it returns data based on that parameter. However, if I pass a blank, I would like that everything in the table be returned.
I have posted some code, as you see....the #id parameter selects only those of that ID correctly but I'd like to know what I should add (or remove) so if this parameter is blank everything is return.
Thank you
CREATE PROCEDURE [dbo].[select_stuent]
#id varchar(25)
AS
CREATE TABLE dbo.#usp_holder (name varchar(25),
id char(5),
class varchar (25),
grade numeric(5)
)
INSERT INTO #usp_ holder (name, id, class)
SELECT
name, id, class
FROM
dbo.classmaster
INNER JOIN
dbo.classtypes ON classmaster.type = classtypes.type
WHERE
classmaster.id = #id;
Try this:
CREATE PROCEDURE [dbo].[select_stuent]
#id varchar(25)
AS
CREATE TABLE dbo.#usp_holder
(
name varchar(25),
id char(5) = null,
class varchar (25)
)
You may want to add another condition to check if the input is an empty string but not null. Like this:
IF (#id = '')
BEGIN
SET #id = null
END
INSERT INTO
#usp_ holder (name,id,class
)
Select name,id,class
from dbo.classmaster
inner join dbo.classtypes
on classmaster.type= classtypes.type
WHERE classmaster.id = ISNULL(#id, classmaster.id)
Related
I created this stored procedure to go through all the records in the table comparing the id (primary key) if exists and the records changed, make the necessary changes & update the record.
If the id is not in the table then insert the record. This stored procedure
compiles fine, but doesn't seem to work properly. Does this need a while loop?
ALTER PROCEDURE [dbo].[SMLineUpdate]
(
#id [int],
#Payroll_Id [int],
#ProductCode nvarchar(255),
#Description nvarchar (255),
#Qty nvarchar(255)
)
AS
IF EXISTS (SELECT Id from Smline where #id = Id) BEGIN
update dbo.SmLine
Set [Payroll_Id] = #Payroll_Id
, ProductCode = #ProductCode
, Description = #Description
, Qty = #Qty
END ELSE BEGIN
INSERT INTO SmLine ([Payroll_Id], [ProductCode], [Description], [Qty])
VALUES (#Payroll_Id, #ProductCode, #Description, #Qty)
END
Your update query is missing a where condition
update dbo.SmLine
Set [Payroll_Id] = #Payroll_Id
,ProductCode = #ProductCode
,Description = #Description
,Qty = #Qty
WHERE Id = #Id -- the query missed this where condition
IF EXISTS(SELECT Id from Smline where Id =#id)
BEGIN
update dbo.SmLine
Set [Payroll_Id]= #Payroll_Id
,ProductCode= #ProductCode
,Description = #Description
,Qty = #Qty
WHERE Id = #Id
END
ELSE
BEGIN
INSERT INTO SmLine ([Payroll_Id],[ProductCode],[Description],[Qty])
VALUES (#Payroll_Id,#ProductCode ,#Description,#Qty)
END
Your SP does not meet the requirement of insert multiple records. It works only for a single record update or inserts, you have to pass multiple id's and values respectively for update multiple so use a different approach like XML as an input parameter so u can simply do this operation for multiple by extracting the XML data.
Your update statement lacks a where statement. That is a major 'no-no', as it will (god forbid...) update all lines in the table.
Your insert statement lacks an identity insert, so consider the case where you are trying to update/insert id=5, but by now this line is deleted (not found in the where), and ids are much bigger. you would search for it -- > not find, and insert a new line (say id=101), then look for id=5 again, not find it again, and insert it again (say id=102), and so on... I don't think that's what you intended. Consider a Merge statement (when matched/when not matched) and get the best of both worlds. Also consider not deleting from the table, and instead add an 'IsDeleted' column (which allows 'reviving' a deleted row).
I am trying to trigger a stored procedure to take the inserted values into my stored procedure as parameters and it is not letting me.
My table flow goes like this: a patient's history information will be inserted (HISTORY_APPOINTMENTS) and if at the time the patient has a column value of HasSuicidalThoughts = 'Y' I want the trigger to send the inserted patients information into a table I created called SuicideWatchLog.
First I created the table:
/* Table Creation for SuicideWatch Log*/
CREATE TABLE SuicideWatchLog
(
logNum integer IDENTITY(1,1) NOT NULL PRIMARY KEY,
PatientStudy# integer FOREIGN KEY References Patients(PatientStudy#),
PatientName varchar(20),
[Date] date,
Dr# integer FOREIGN KEY References DOCTORS(Dr#),
DaysinStudy integer
)
Next I created the procedure:
CREATE PROCEDURE AddSuicideWatch
#PatientStudy# integer,
#PatientName varchar(20),
#Date date,
#Dr# integer,
#DaysinStudy integer
AS
BEGIN
INSERT INTO SuicideWatchLog(PatientStudy#, Date, Dr#)
(SELECT PatientStudy#, ApptDate, Dr#
FROM APPOINTMENTS
WHERE #PatientStudy# = PatientStudy#
AND #Date = ApptDate
AND #Dr# = Dr#)
INSERT INTO SuicideWatchLog(PatientName, DaysinStudy)
(SELECT PatientFName, datediff(day,StudyStartDate,getdate())
FROM PATIENTS
WHERE #PatientName = PatientFName
AND #DaysinStudy = datediff(day,StudyStartDate,getdate()))
END
Finally I created the trigger:
CREATE TRIGGER SuicidalPatient
ON HISTORY_APPOINTMENT
AFTER INSERT
AS
EXEC AddSuicideWatch(
SELECT (I.PatientStudy#, P.PatientFName, A.ApptDate,
FROM INSERTED I
JOIN APPOINTMENTS A ON I.Appt# = A.Appt#
JOIN PATIENTS P ON I.PatientStudy# = P.PatientStudy#)
I expected this to allow me to send the inserted values into the stored procedure to trigger the creation of the log, but instead I am getting an error that is telling me my parameters aren't being found.
Is this an issue with the select statement, or is it a problem with the procedure itself?
Is this an issue with the select statement, or is it a problem with the procedure itself?
Your stored procedure accepts scalar parameters. You can't pass a whole resultset to it. You can:
1) Integrate the INSERTs directly into the trigger body, eliminating the stored procedure.
2) Open a cursor over the query in the trigger, and loop through the rows, calling the stored procedure fore each one.
3) Declare a User-Defined Table Type matching the query result rows, declare and load an instance of the table type in the trigger body, and change the stored procedure to accept a Table-Valued Parameter.
you cant pass table to sp , but i know 2 ways for that :
1- use user defined type like that :
create type NewTable AS table (PatientStudy# int, PatientFName nvarchar(max), ApptDate date)
and the insert into NewTable Then call sp
declare #TempTable NewTable
insert into #TempTable(PatientStudy# , PatientFName , ApptDate)
select I.PatientStudy#, P.PatientFName, A.ApptDate,
FROM INSERTED I
JOIN APPOINTMENTS A ON I.Appt# = A.Appt#
JOIN PATIENTS P ON I.PatientStudy# = P.PatientStudy#
EXEC AddSuicideWatch( #TempTable)
and of course you should edit your SP :
CREATE PROCEDURE AddSuicideWatch
#Table NewTable
AS
BEGIN
INSERT INTO SuicideWatchLog(PatientStudy#, Date, Dr#)
SELECT PatientStudy#, ApptDate, Dr#
FROM APPOINTMENTS A join #Table T ON
A.PatientStudy# = T.PatientStudy#
A.Date = T.ApptDate
A.Dr# = D.Dr#
INSERT INTO SuicideWatchLog(PatientName, DaysinStudy)
(SELECT PatientFName, datediff(day,StudyStartDate,getdate())
FROM PATIENTS P join #Table T ON
T.PatientName = P.PatientFName
AND A.DaysinStudy = datediff(day,StudyStartDate,getdate()))
END
And the seccond way : just pass the primary key to sp and handle other things in sp
I tried to create a function with a conditional calculation before the RETURN statement, but SSMS states that there is an incorrect syntax near 'BEGIN IF #param2 IS NULL' and I can't figure out what is wrong with this code:
CREATE FUNCTION ConditionalFunction
(
#input1 VARCHAR(20),
#input2 VARCHAR(20)
)
RETURNS TABLE
AS BEGIN
IF #input2 IS NULL
BEGIN
SET #input2 = field
FROM table1
WHERE filter = #input1
END
RETURN
(
SELECT field1, field2
FROM table2
WHERE filter1 = #input1
AND filter2 = #input2
)
END
My goal is to be able to call it either
ConditionalFunction('Foo',NULL)
or
ConditionalFunction('Foo','Bar')
In a way that the first call will make it detect a default value for #input2 based on #input1.
I wrote this code based on this answer.
This is SQL Server 13. Could you please tell me if there is anything I can do to make it compile?
N.B: I obviously replaced real names with generics, but the code structure remains the same
Try this, but change the #Data table types to your data types:
CREATE FUNCTION ConditionalFunction
(
#input1 VARCHAR(20),
#input2 VARCHAR(20)
)
RETURNS #Data TABLE
(
field1 VARCHAR(12)
,field2 VARCHAR(12)
)
AS
BEGIN
IF #input2 IS NULL
BEGIN
SET #input2 = field
FROM table1
WHERE filter = #input1
END
INSERT INTO #Data
SELECT field1, field2
FROM table2
WHERE filter1 = #input1
AND filter2 = #input2
RETURN;
END
There are several types of functions in SQL:
scalar return only one value
inline - returns a table (it is like view with parameters)
table-valued - returns a table
Your syntax looks like you need a inline function, but should contain only one SELECT statement returning the data. So, you need to create a table-valued function.
Is there a way to select top 1 row from 'User Defined Table Type' which is passed as a parameter to Stored Procedure?
CREATE TYPE t1 as TABLE
(
id INT,
name VARCHAR(100)
)
SP
CREATE STORED PROCEDURE sp1
(
#type dbo.t1 as READONLY
)
BEGIN
SELECT TOP 1 name FROM #type
END
Any Ideas?
Your stored procedure should probably be something like this:
CREATE STORED PROCEDURE sp1
(
#type dbo.t1 READONLY
)
BEGIN
SELECT TOP 1 name
FROM #type t1
ORDER BY id
END
Notes:
I've removed the as keyword
using TOP n without using the ORDER BY clause will return a single row, but there is no guarantee what row it will be, since database tables are un sorted by nature.
Look at below working example, which give detail idea about how to CREATE/PASS/CALL user defined Table Type from SP.
User Defined Table Type Creation Script:
CREATE TYPE [dbo].[IdCenterIdList] AS TABLE(
[Id] [varchar](36) NOT NULL,
[CenterId] [varchar](36) NOT NULL
)
SP Creation:
CREATE PROCEDURE TestType
#IdCenterIdList AS IdCenterIdList ReadOnly
AS
BEGIN
SELECT
TOP(1) *
FROM #IdCenterIdList
END
GO
SP Execute Statement:
DECLARE #tblTestType IdCenterIdList
INSERT INTO #tblTestType VALUES('11','1111')
,('22','222')
,('33','333')
EXEC TestType #tblTestType
Output:
I want to run a stored procedure on each ID return by a SELECT query. Is there a simple way to do something like:
FOREACH (SELECT ID FROM myTABLE WHERE myName='bob') AS id
BEGIN
EXEC #return_value = [dbo].[spMYPROC]
#PARAM1 = id
#PARAM2 = 0
END
Since I just happened to answer a very similar question yesterday, I have this code handy. As others have stated, it may not be the best approach, but still it's nice to learn how to use a while loop anyway.
Assuming a table named "Customer"
declare #Id int
select #Id = MIN(Id)
from Customer c
while(select COUNT(1)
from Customer c
where c.Id >= #Id) > 0
begin
--run your sproc right here
select #Id = MIN(Id)
from Customer c
where c.Id > #Id
end
DECLARE #ID INT, #return_value INT
DECLARE c CURSOR FOR
SELECT
ID
FROM myTABLE
WHERE myName = 'bob'
OPEN c; FETCH NEXT FROM c INTO #ID
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC #return_value = [dbo].[spMYPROC]
#PARAM1 = #ID,
#PARAM2 = 0
FETCH NEXT FROM c INTO #ID
END
CLOSE c; DEALLOCATE c;
You have two option here
Option 1 Using Split Function
Pass a comma deliminated list of IDs and use a Split function Inside your Procedure to make split these values and do whatever you want to do with it.
To
Make it work you will need two thing
1) Create a Function which
accepts a Comma Deliminated string and split them.
2) Modify you
Store Procedure and add this function in there in a way that passed
parameter is passed to the function inside that store procedure and
that function split the values before passing it onto your store
Procedure .
Create this function 1st
Function Definition
CREATE FUNCTION [dbo].[FnSplit]
(
#List nvarchar(2000),
#SplitOn nvarchar(5)
)
RETURNS #RtnValue table (Id int identity(1,1), Value nvarchar(100))
AS
BEGIN
WHILE(Charindex(#SplitOn,#List)>0)
BEGIN
INSERT INTO #RtnValue (value)
SELECT VALUE = ltrim(rtrim(Substring(#List,1,Charindex(#SplitOn,#List)-1)))
SET #List = SUBSTRING(#List,Charindex(#SplitOn,#List)+len(#SplitOn),len(#List))
END
INSERT INTO #RtnValue (Value)
SELECT VALUE = ltrim(rtrim(#List))
RETURN
END
Modify you strored Procedure something like this
Stored Procedure
ALTER Procedure [dbo].[spMYPROC] (#Param1 VARCHAR(1000)= NULL)
AS
BEGIN
SELECT * FROM TableName
where ColumnNAME IN (SELECT Value FROM dbo.FnSplit(#Param1,','))
END
GO
Option 2 Table Type Parameter
Create a Table Type and alter your proc to accept a Table Type Parameter and do whatever you want to do with them values inside your proc.
TABLE TYPE
CREATE TYPE dbo.TYPENAME AS TABLE
(
Value int
)
GO
Stored Procedure to Accept That Type Param
ALTER PROCEDURE [dbo].[spMYPROC]
#TableParam TYPENAME READONLY
AS
BEGIN
SET NOCOUNT ON;
--Temp table to store passed Id values
declare #tmp_values table (value INT );
--Insert passed values to a table variable inside the proc
INSERT INTO #tmp_values (value)
SELECT Value FROM #TableParam
/* Do your stuff here whatever you want to do with Ids */
END
EXECUTE PROC
Declare a variable of that type and populate it with your values.
DECLARE #Table TYPENAME --<-- Variable of this TYPE
INSERT INTO #Table --<-- Populating the variable
SELECT ID FROM myTABLE WHERE myName='bob'
EXECUTE [dbo].[spMYPROC] #Table --<-- Stored Procedure Executed