I have a sql table which has one column "type". It has values A,B,C,D.
I'm writing a stored procedure in which type is the in parameter #type.
#type can has either value 'A' or 'A,B,C' or 'ALL' based on user selection on screen. Which means user can select single,multiple or ALL options.
I need to filter data from my table with condition on column "type".
I want something similar to below
select * from maintable where
( case when #type ='ALL' then 1=1) else
type in (select data from SplitString(#type,',')) end)
I have written a split function which return values in a table format.
When ALL is selected then the whole table should be returned. When specific type(s) is selected, only those types should be returned.
I'm using sqlserver 2012.
Kindly help!!
Try this
SELECT *
FROM maintable
WHERE #type ='ALL' OR
(#type <>'ALL' AND TYPE IN (SELECT data FROM SplitString(#type,','))
You can do it like below :
if #type ='ALL'
set #type ='A,B,C,D'
select * from maintable where
type in (select data from SplitString(#type, ','))
You can use an IF:
IF #type ='ALL'
SELECT *
FROM MainTable
ELSE
SELECT *
FROM MainTable
WHERE Type IN (SELECT data FROM SplitString(#type,',') )
Related
I couldn't even think of how to phrase this properly for the title.
I have an SSRS report with a multi-valued parameter called Department.
If the user IS IN Department A..We want to default to all departments EXCEPT department A
If the user IS NOT IN Department A..We want to default to only their department
Department A will never be in the parameter list but being a member of department A impacts what you will see.
I know that I could resolve this with an ALL parameter option, but I would prefer the only parameter values to be valid department names
My parameter is populated with two datasets.
The first dataset has three options for valid departments: EUR, REM, LIFA
The second dataset only determines the current user's department and would populate the default. IF the current user's department is CS we want to select the other three departments as the default. If their department <> CS we want to default to only their department.
I thought the code below would work but the concatenated string is not an option in the first dataset so it cannot be the default option
SELECT DISTINCT
CASE
WHEN EmployeePracticeArea = 'CS'
THEN 'EUR, LIFA, REM'
ELSE EmployeePracticeArea
END AS 'EmployeePracticeArea'
FROM DimEmployee
WHERE
(EmployeePracticeArea <> '')
AND (UserLogin = #CurrentUser)
The problem with the case statement is that it tries to set a default value of EUR, LIFA, REM. This string does not exist in the 'options' list of values. The options are the three seperate strings EUR, LIFA, REM.
Case statements cannot return multiple values so I need to evaluate the current user's department and then return a list without it
Here is something which will generate the dataset for you
IF OBJECT_ID('tempdb..#TestData') IS NOT NULL
DROP TABLE #TestData;
WITH Data (EmployeePracticeArea) AS (
SELECT 'LIFA'
UNION
SELECT 'REM'
UNION
SELECT 'EUR'
UNION
SELECT 'CS'
)
SELECT * INTO #TestData FROM Data ;
The end result is like this:
User1 in the LIFA department has his parameter defaulted to just LIFA
User2 in the CS department has his parameter defaulted to EUR, LIFA, REM
DECLARE #t TABLE(Dept varchar(4))
DECLARE #CurrentUserDept varchar(4) = (SELECT EmployeePracticeArea FROM dimEmployee WHERE UserLogin = #CurrentUser)
IF #CurrentUserDept = 'CS'
BEGIN
INSERT INTO #t VALUES ('EUR'), ('LIFA'), ('REM')
END
ELSE
BEGIN
INSERT INTO #t SELECT #CurrentUserDept
END
SELECT * FROM #t
I'm quite new to T-SQL and currently struggling with an insert statement in my stored procedure: I use as a parameter in the stored procedure a list of ids of type INT.
If the list is NOT empty, I want to store the ids into the table Delivery.
To pass the list of ids, i use a table type:
CREATE TYPE tIdList AS TABLE
(
ID INT NULL
);
GO
Maybe you know a better way to pass a list of ids into a stored procedure?
However, my procedure looks as follows:
-- parameter
#DeliveryModelIds tIdList READONLY
...
DECLARE #StoreId INT = 1;
-- Delivery
IF EXISTS (SELECT * FROM #DeliveryModelIds)
INSERT [MyDB].[Delivery] ([DeliveryModelId], [StoreId])
OUTPUT inserted.DeliveryId
SELECT ID FROM #DeliveryModelIds;
If the list has values, I want to store the values into the DB as well as the StoreId which is always 1.
If I insert the DeliveryIds 3,7,5 The result in table Delivery should look like this:
DeliveryId | StoreId | DeliveryModelId
1...............| 1...........| 3
2...............| 1...........| 7
3...............| 1...........| 5
Do you have an idea on how to solve this issue?
THANKS !
You can add #StoreId to your select for your insert.
...
IF EXISTS (SELECT * FROM #DeliveryModelIds)
INSERT [MyDB].[Delivery] ([DeliveryModelId], [StoreId])
OUTPUT inserted.DeliveryId
SELECT ID, #StoreId FROM #DeliveryModelIds;
Additionally, if you only want to insert DeliveryModelId that do not currently exist in the target table, you can use not exists() in the where clause like so:
...
IF EXISTS (SELECT * FROM #DeliveryModelIds)
INSERT [MyDB].[Delivery] ([DeliveryModelId], [StoreId])
OUTPUT inserted.DeliveryId
SELECT dmi.ID, #StoreId
FROM #DeliveryModelIds dmi
where not exists (
select 1
from MyDb.Delivery i
where i.StoreId = #StoreId
and i.DeliveryModeId = dmi.ID
);
You need to modify the INSERT statement to:
INSERT [MyDB].[Delivery] ([DeliveryModelId], [StoreId])
OUTPUT inserted.DeliveryId
SELECT ID, 1 FROM #DeliveryModelIds;
So you are also selecting a literal, 1, along with ID field.
Using SQL Server 2000; I am trying to determine the action if a value in a field of the INSERTED record matches one of several distinct values in a field in a table. Field y in tableB could be say 'one', 'two' or 'three'. The INSERTED record must be a single record, and therefore the field x must be a single value. Hence, given the code snippet below, what is the correct syntax? In particular where do the "()" go in the IF statement?
if select x from INSERTED in (select y from tableB)
and <another condition>
begin
<some code>
end
The correct syntax is
IF EXISTS (SELECT * FROM TABLE1 WHERE X IN (1,2))
Begin
-- code
End
You can store the individual flag in variables and use that in IF condition.
Declare #chkExist int
Select #chkExist = Count(*) from tableA x in (select y from tableB)
if ((#chkExist > 0) and (<another condition>))
begin
<some code>
end
Try a "where exists" instead of "IN"
if exists ( select null from tableA taAlias where (select null from tableB tbAlias where tbAlias.y = taAlias.x ) )
and 1=1
begin
Select 1 as 'YouNeedAtLeastOneLineOfCodeInThisBeginEnd'
end
I created a user-defined function in SQL Server 2012 that returns XML. I would like to call the function in a SELECT statement. Is this possible?
When I try doing it, I get the error:
The FOR XML clause is not allowed in a ASSIGNMENT statement.
I want the SELECT statement to return a set of these named methods that have dependencies of other named methods within their logic.
In the main CTE, I get the latest versions of methods that have dependencies. The UDF goes thru the logic of each method and returns any methods called within it. So, I want to call the UDF in the SELECT statement and return XML of the dependent method names.
The function works and returns XML data. This is the function:
ALTER FUNCTION [dbo].[GetCalledMLMs]
(
-- Add the parameters for the function here
#MLM_Txt nvarchar(MAX)
)
RETURNS XML
AS
BEGIN
-- Declare the return variable here
DECLARE #CalledMLMs XML
Declare #MLMTbl table (pos int, endpos int, CalledMLM nvarchar(200))
--Logic to get the data...
Select #CalledMLMs = CalledMLM from #MLMTbl FOR XML PATH
-- Return the result of the function
RETURN #CalledMLMs
END
This is the CTE that calls the UDF.
;with cte as
(
select distinct Name, max(ID) as LatestVersion
from MLM_T
where Logic like '%:= MLM %' and Logic not like '%standard_libs := mlm%'
group by Name
)
select MLM2.Name, LatestVersion,
dbo.GetCalledMLMs(MLM2.Logic) as CalledMLMs
from cte join MLM_T MLM2 on cte.Name = MLM2.Name
and cte.LatestVersion = MLM2.ID
and MLM2.Active = 1 and MLM2.Status in (3, 4)
When running this query I get the error that XML is not allowed to be used in assignment statement.
Is there any way to call a function in the SELECT statment that returns an XML data type?
If you want to set a variable to a value you have to use SET and a scalar value on the right side.
The syntax SELECT #SomeVariable=SomeColumn FROM SomeTable is not possible with FOR XML (and rather dangerous anyway...), because the XML is not a column of the SELECT but something after the process of selecting.
Your problem is situated here:
Select #CalledMLMs = CalledMLM from #MLMTbl FOR XML PATH
Try to change this to
SET #CalledMLMs = (SELECT CalledMLM FROM #MLMTbl FRO XML PATH);
I solved the problem by changing the function to return a table, not XML.
So it looks like this:
FUNCTION [dbo].[GetCalledMLMsTbl]
(
-- Add the parameters for the function here
#MLM_Txt nvarchar(MAX)
)
--RETURNS XML
RETURNS #MLMTbl TABLE
(
pos int,
endpos int,
CalledMLM nvarchar(200)
)
AS
BEGIN
--logic here
insert into #MLMTbl (pos, endpos, CalledMLM) Values (#startpos, #endpos, #MLM_name)
RETURN
END
Then I called the function in the 'from' clause in the select
;with cte as
(
select distinct Name, max(ID) as LatestVersion
from CV3MLM
where Logic like '%:= MLM %' and Logic not like '%standard_libs := mlm%'
--and Name not like '%V61_CCC'
group by Name
)
select MLM2.Name, LatestVersion, C.CalledMLM
from cte join MLM_tbl MLM2 on cte.Name = MLM2.Name and cte.LatestVersion = MLM2.ID
and MLM2.Active = 1 and MLM2.Status in (3, 4)
cross apply dbo.GetCalledMLMsTbl(MLM2.Logic) C
order by MLM2.Name, LatestVersion
I have a stored procedure that receives a TVP as input. Now, I need to check the received data for a particular ID in a primary key column. If it exists, then I just need to update the table using those new values for other column (sent via TVP). Else, do an insert.
How to do it?
CREATE PROCEDURE ABC
#tvp MyTable READONLY
AS
IF EXISTS (SELECT 1 FROM MYTAB WHERE ID= #tvp.ID)
DO update
ELSE
Create
Just wondering the if exists loop I did is correct. I reckon its wrong as it will only check for first value and then update. What about other values? How should I loop through this?
Looping/CURSOR is the weapon of last resort, always search for solution that is SET based, not ROW based.
You should use MERGE which is designed for this type of operation:
MERGE table_name AS TGT
USING (SELECT * FROM #tvp) AS SRC
ON TGT.id = SRC.ID
WHEN MATCHED THEN
UPDATE SET col = SRC.col
WHEN NOT MATCHED THEN
INSERT (col_name, col_name2, ...)
VALUES (SRC.col_name1, SRC.col_name2, ...)
If you don't like MERGE use INSERT/UPDATE:
UPDATE table_name
SET col = tv.col,
...
FROM table_name AS tab
JOIN #tvp AS tv
ON tab.id = tv.id
INSERT INTO table_name(col1, col2, ...)
SELECT tv.col1, tv.col2, ...
FROM table_name AS tab
RIGHT JOIN #tvp AS tv
ON tab.id = tv.id
WHERE tab.id IS NULL