IF NOT EXISTS (SELECT TOP 1 CityName FROM dbo.City WHERE [Name] = 'Default City')
BEGIN
INSERT dbo.City ( CityName, Status,CityCategoryId) VALUES
(N'Default City', 0, (SELECT CityCategoryId FROM dbo.CityCategory WHERE [CityCategoryName] = N'Default City Category'))
END
GO
i have the the above query which runs fine in SQL server 2012 but fails in SQL Server 2005 with the below error message.
Subqueries are not allowed in this context. Only scalar expressions are allowed.
Change your insert like this.
INSERT dbo.City
(CityName,Status,CityCategoryId)
SELECT N'Default City',0,CityCategoryId
FROM dbo.CityCategory
WHERE [CityCategoryName] = N'Default City Category'
Try using variable #CityCategoryId. I don't know the type of #CityCategoryId. You can use datatype that you want.
IF NOT EXISTS (SELECT TOP 1 CityName FROM dbo.City WHERE [Name] = 'Default City')
BEGIN
Declare #CityCategoryId AS NVARCHAR(100)
SELECT #CityCategoryId = CityCategoryId FROM dbo.CityCategory
WHERE [CityCategoryName] = N'Default City Category'
INSERT dbo.City( CityName, Status, CityCategoryId)
VALUES
(N'Default City', 0, #CityCategoryId)
END
GO
Try like this. Am not sure...
IF NOT EXISTS (SELECT TOP 1 CityName FROM dbo.City WHERE [Name] = 'Default City')
BEGIN
INSERT dbo.City ( CityName, Status,CityCategoryId)
SELECT 'Default City',0, CityCategoryId FROM dbo.CityCategory WHERE [CityCategoryName] = N'Default City Category'
END
GO
Related
I'm writing a stored procedure that runs different selects based on the user role , this is just an example to showcase my intention since i have a lot of roles to work with.
IF OBJECT_ID('dbo.spSelectArtigos') IS NOT NULL
DROP PROCEDURE spSelectArtigos
GO
CREATE PROCEDURE spSelectArtigos
#IdUser int,
#Acesso nvarchar(20)
AS
BEGIN
IF(#Acesso = 'User')
SELECT col1,col2 from table1 where IdUser = #IdUser
IF(#Acesso = 'Logistica')
SELECT col1,col2,col3 from table1 where IdUser = #IdUser
IF(#Acesso = 'Admin')
SELECT * From table1
END
Is there a more effective way to do this with less code using some sort of logic?
IDK why i added a check to make sure the user actually exists but it isnt a bad idea
IF OBJECT_ID('dbo.spSelectArtigos') IS NOT NULL
DROP PROCEDURE spSelectArtigos
GO
CREATE PROCEDURE spSelectArtigos
#IdUser int,
#Acesso nvarchar(20)
AS
BEGIN
CASE
WHEN #Acesso ='User'
AND
EXISTS (SELECT * FROM table1 WHERE IdUser = #IdUser)
THEN
SELECT col1,col2 from table1 where IdUser = #IdUser
WHEN #Acesso ='Logistica' Then
AND
EXISTS (SELECT * FROM table1 WHERE IdUser = #IdUser)
THEN
SELECT col1,col2,col3 from table1 where IdUser = #IdUser
WHEN #Acesso ='Admin'
AND
EXISTS (SELECT * FROM table1 WHERE IdUser = #IdUser)
THEN
SELECT * From table1
END
END
Here is a kludgy way but it is concise.
IF OBJECT_ID('dbo.spSelectArtigos') IS NOT NULL
DROP PROCEDURE spSelectArtigos
GO
CREATE PROCEDURE spSelectArtigos
#IdUser int,
#Acesso nvarchar(20)
AS
BEGIN
DECLARE #Result TABLE(A INT,B INT,C INT,D INT)
INSERT #Result SELECT A,B,C,D FROM table1 WHERE idUser=#idUser
IF(#Acesso = 'User')
UPDATE #Result SET C=NULL, D=NULL
IF(#Acesso = 'Logistica')
UPDATE #Result SET D=NULL
SELECT * From #Result
END
Another way but dealing with ID's
SELECT
A=CASE WHEN #Acesso >= 10 THEN A ELSE NULL END,
B=CASE WHEN #Acesso >= 20 THEN B ELSE NULL END,
C=CASE WHEN #Acesso >= 99 THEN C ELSE NULL END
FROM
table1
WHERE
idUser=#idUser
How would I return a table from a SQL Server function?
In Postgres, I would simply do something like the following:
CREATE FUNCTION table_get(_active_bool BOOLEAN)
RETURNS TABLE(column integer)
language plpgsql
as $$
BEGIN
RETURN QUERY
SELECT column
FROM table
WHERE active = _active_bool
END;
$$;
And it will just work.
For what ever reason I can't get this one to work in SQL Server.
CREATE FUNCTION hr.naughty_emp_id_get
(#pquarter NVARCHAR(1),
#pyear NVARCHAR(4))
RETURNS TABLE (employeeid INT)
AS
BEGIN
WITH vars AS
(
SELECT #pquarter AS pquarter, #pyear AS pyear
)
SELECT tblhr_employees.employeeid
FROM hr.tblhr_employees
INNER JOIN hr.tblHR_AttendancePunchTime ON tblhr_employees.employeeid = tblHR_AttendancePunchTime.EmployeeID
INNER JOIN hr.tblHR_AttendanceTimeCode ON tblHR_AttendancePunchTime.CodeID = tblHR_AttendanceTimeCode.CodeID
WHERE 1 = 1
AND (tblHR_AttendanceTimeCode.CategoryID = 3
OR tblHR_AttendanceTimeCode.CategoryID = 11)
AND dbo.to_year_quarter(tblHR_AttendancePunchTime.AdjTimeIn) = (SELECT vars.pyear FROM vars) + '-' + (SELECT vars.pquarter FROM vars)
AND tblhr_employees.separationdate IS NULL
GROUP BY
tblhr_employees.employeeid;
RETURN
END
GO
It is throwing this error:
Msg 156, Level 15, State 1, Procedure naughty_emp_id_get, Line 18 [Batch Start Line 6]
Incorrect syntax near the keyword 'BEGIN'
I tried adding ;s in various spots and it didn't seem to work
You are missing the table name for the table to be returned. This should work
CREATE FUNCTION hr.naughty_emp_id_get
(
-- Add the parameters for the function here
#pquarter NVARCHAR(1)
, #pyear NVARCHAR(4)
)
RETURNS #employees TABLE (employeeid INT)
AS
BEGIN
WITH vars AS (SELECT #pquarter AS pquarter, #pyear AS pyear)
INSERT #employees
SELECT tblhr_employees.employeeid
FROM hr.tblhr_employees
INNER JOIN hr.tblHR_AttendancePunchTime ON tblhr_employees.employeeid = tblHR_AttendancePunchTime.EmployeeID
INNER JOIN hr.tblHR_AttendanceTimeCode ON tblHR_AttendancePunchTime.CodeID = tblHR_AttendanceTimeCode.CodeID
WHERE 1=1
AND (tblHR_AttendanceTimeCode.CategoryID = 3
OR tblHR_AttendanceTimeCode.CategoryID = 11)
AND dbo.to_year_quarter(tblHR_AttendancePunchTime.AdjTimeIn) = (SELECT vars.pyear FROM vars) + '-' + (SELECT vars.pquarter FROM vars)
AND tblhr_employees.separationdate IS NULL
GROUP BY tblhr_employees.employeeid;
RETURN
END
You have mixed 2 ways of declaring the resulting temporal table.
Either declare as table variable and explicitly insert into it:
CREATE FUNCTION hr.naughty_emp_id_get
(
#pquarter NVARCHAR(1)
, #pyear NVARCHAR(4)
)
RETURNS #result TABLE (employeeid INT) -- Here
AS
BEGIN
;WITH vars AS (SELECT #pquarter AS pquarter, #pyear AS pyear)
INSERT INTO #result (employeeid) -- And here
SELECT tblhr_employees.employeeid
FROM --...
END
Or avoid it's declaration altogether:
CREATE FUNCTION hr.naughty_emp_id_get
(
-- Add the parameters for the function here
#pquarter NVARCHAR(1)
, #pyear NVARCHAR(4)
)
RETURNS TABLE AS RETURN
WITH vars AS (SELECT #pquarter AS pquarter, #pyear AS pyear)
SELECT tblhr_employees.employeeid
FROM --...
You have to insert into the resulting table variable.
RETURNS #MyTable TABLE (MyID INT)
AS BEGIN
INSERT INTO #MyTable SELECT 1
RETURN
END
I am having six select queries with different where conditions if first select query returns null it should check the next select query and follows. what is the best approach to follow for writing it as stored procedure in SQL server.
You can use ##rowcount
DECLARE #OperatorID INT = 4, #CurrentCalendarView VARCHAR(50) = 'month';
declare #t table (operatorID int, CurrentCalendarView varchar(50));
insert into #t values (2, 'year');
select operatorID - 1, CurrentCalendarView from #t where 1 = 2
if (##ROWCOUNT = 0)
begin
select operatorID + 1, CurrentCalendarView from #t where 1 = 1
end
If I understand your question correctly then you can achieve this like below sample. You can go in this way.
if NOT EXISTS (SELECT TOP(1) 'x' FROM table WHERE id =#myId)
BEGIN
IF NOT EXISTS (SELECT TOP(1) 'x' FROM table2 WHERE id = #myId2)
BEGIN
IF NOT EXISTS (SELECT TOP(1) 'x' FROM table 3 WHERE id = #myID3)
BEGIN
END
END
END
Problem Statement :
when #a has a single word(Ex. 'name1') OR comma separated string (Example 'name1,name2,name3') then the query should return the manager names of employees with name1 and name2 and name3
when #a has an empty string then return the manager names of all the employees in the emp_master table
I have defined a stored procedure where I pass a variable.
This variable can be a comma separated string, a single word or an empty string.
If the string is comma separated then I split that string and get values based on the return table of split statement
else
I get the related value of the non comma separated data using normal subquery
I have tried to achieve this in the following way
Declare #a varchar(50)= ''
select emp.Name from
emp_master emp
where
(LEN(#a)=0 AND emp.Name in
(
SELECT DISTINCT [Name] FROM
[dbo].[Emp_Master] WHERE [EmpId] IN
(
SELECT
DISTINCT [MGR_ID]
FROM [dbo].[Emp_Master]
)
)
)
OR
emp.Name in (Select * from [dbo].[SplitString](#a, ','))
Details for the above sample:
[dbo].[SplitString] - custom written function : returns a table of split values. So
Select * from [dbo].SplitString
will return
SplitTable
----------
name1
name2
name3
and
Select * from [dbo].[SplitString](',','name1')
will return
SplitTable
----------
name1
[dbo].[Emp_Master] contains data for all the employees
[MGR_ID] is the column which has the employeeID of the employee manager
#a is the input variable
The Database is MS SQL 2008
My current solution(the above insane query) solves my purpose but it is very slow, it would be helpful to get an optimized and faster working solution for the problem
Emp_master Table has 400 000 rows, 30 columns
There are 18 000 managers in that table
CREATE NONCLUSTERED INDEX ix ON dbo.Emp_Master ([MGR_ID])
GO
DECLARE #a VARCHAR(50) = ''
DECLARE #t TABLE (val VARCHAR(50) PRIMARY KEY WITH(IGNORE_DUP_KEY=ON))
INSERT INTO #t
SELECT item = t.c.value('.', 'INT')
FROM (
SELECT txml = CAST('<r>' + REPLACE(#a, ',', '</r><r>') + '</r>' AS XML)
) r
CROSS APPLY txml.nodes('/r') t(c)
SELECT /*DISTINCT*/ [Name]
FROM dbo.Emp_Master e1
WHERE (
#a = ''
AND
e1.[EmpId] IN (SELECT DISTINCT MGR_ID FROM dbo.Emp_Master)
)
OR (
#a != ''
AND
e.Name IN (SELECT * FROM #t)
)
OPTION(RECOMPILE)
TRY THIS
CREATE NONCLUSTERED INDEX IX_MGR_ID_Emp_Master ON dbo.Emp_Master ([MGR_ID])
GO
Create Procedure searchname (#a varchar(255))
as
IF (#a = '')
BEGIN
EXEC Searchname1 #a
END
ELSE
BEGIN
EXEC Searchname2 #a
END
GO
Create Procedure Searchname1 (#a varchar(255))
AS
SELECT DISTINCT [Name] FROM
[dbo].[Emp_Master] m1 WHERE
exists
(
SELECT
*
FROM [dbo].[Emp_Master] m2
WHERE
m1.[EmpId]= m2.[MGR_ID]
)
GO
Create Procedure Searchname2 (#a varchar(max))
AS
Select #a = ' SELECT '''+replace( #a,',',''' Union ALL SELECT ''')+' '''
Create table #names (name varchar(255))
insert into #names
EXEC ( #a )
select emp.Name from
emp_master emp
WHERE
emp.Name in( Select name FRom #names)
option (recompile)
IF YOU ARE ALREADY DEALING WITH SQL INJECTION AT APPLICATION LEVEL
THEN
ALTER procedure [dbo].[Searchname2] (#a varchar(max))
AS
select #a = ''''+replace ( #a,',',''',''')+''''
DECLARE #sql NVARCHAR(MAX) = N'
select distinct emp.Name from
emp_master emp
WHERE
emp.Name in( '+#a+')'
EXEC (#sql)
How to merge these 2 select statements so that 3 columns are returned?
the first select only returns text values whereas the second select returns a table column value. If the second table returns no value, still the first select should have value and the name column can be null
SELECT 'column1', 'column2'
SELECT Name
FROM [dbo].[TableName]
WHERE ID = #id
Many thanks,
Do you mean something like this:
SELECT 'column1', 'column2', Name
FROM [dbo].[TableName]
WHERE ID = #id
This will return a row for each row with a matching ID in the table.
Update:
This query will do exactly what you want:
IF (SELECT COUNT(Name) FROM [dbo].[TableName] WHERE ID = #id) = 0
BEGIN
SELECT 'column1', 'column2', NULL
END
ELSE
BEGIN
SELECT 'column1', 'column2', Name
FROM [dbo].[TableName]
WHERE ID = #id
END
this would be simpler, no need to duplicate the fixed columns:
DECLARE #name nvarchar(255)
SELECT #name=Name FROM [dbo].[TableName] WHERE ID = #id
SELECT 'column1', 'column2', #name AS 'Name'
You can have one query like this:
SELECT
'column1',
'column2',
(
SELECT Name
FROM [dbo].[TableName]
WHERE ID = #id
) AS 'Name'
If, as seems likely, there can only be at most one match then Andriy or William's solutions are the best. If for some strange reason Id isn't a primary key then the following will do what you want.
SELECT a.column1, a.column2, t.Name
FROM
(
SELECT 'column1' AS column1, 'column2' AS column2
) a
LEFT JOIN [dbo].[TableName] t ON (t.ID = #Id)
I feel kinda dirty....