Syntax error using multiple CTEs - sql

I have a rather complicated CTE that I'm attempting to incorporate into a stored procedure. It works when just operating straight from SQL Server Management Studio. When I try to create my stored procedure, I get an error:
Msg 102, Level 15, State 1, Procedure spMyCrazyProc, Line 56
Incorrect syntax near ','.
What have I syntactically done incorrectly when trying to incorporate my CTE into a stored procedure?
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[spMyCrazyProc]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[spMyCrazyProc]
GO
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE dbo.spMyCrazyProc
#CompanyId Int,
#EmployeeIds varchar(MAX)
AS
;with SelectedEmployees as (
select * from vwEmployee e
where e.CompanyId = #CompanyId
and (#EmployeeIds is null or #EmployeeIds='' or exists(select ce.SelectedEmployeeId from #myTmpTable ce where ce.SelectedEmployeeId=e.EmployeeId)
), MyStuffA as (
select * from SelectedEmployees
)
select * from MyStuffA
GO

Using sensible coding conventions and thinking about readability (indenting, carriage returns) would have yielded this simple error much more clearly. Your code with 500 character-wide lines removed:
;with SelectedEmployees as
(
select * from vwEmployee e
where e.CompanyId = #CompanyId
and
(
#EmployeeIds is null or #EmployeeIds='' or exists
(
select ce.SelectedEmployeeId from #myTmpTable ce
where ce.SelectedEmployeeId=e.EmployeeId
)
----^----- oops! Missing closing paren here.
), MyStuffA as
(
select * from SelectedEmployees
)
select * from MyStuffA

Related

IF in Where with multiple Conditions

I am trying to write a query where I can have either of the 2 variables entered and the query needs to execute on the basis of which data was entered. For example
DECLARE #A NVARCHAR(15) = '' -- Input A here
-------------------OR---------------------
DECLARE #B NVARCHAR(15) = '' -- Input B here
SELECT
[DOC].[ety_ts] as [CreatedDate],
[DOC].[ord_int_id],
[DOC].[doc_int_id],
[pnt_cln_doc_int_id] as [ParentDoc],
CDTL_STATUS2.cod_dtl_ds as DocumentName,
CDTL_STATUS.[cod_dtl_ds] as [DocumentStatus],
.................................
..................................
.....................................
WHERE
IF ( #A IS NULL OR #A = '' )
BEGIN
DOC.asn_int_id = (Select asn_int_id from TPM(nolock) where rec_no=#B)
END
ELSE
BEGIN
DOC.ord_int_id IN
(
SELECT DOC.ord_int_id
FROM TAD_DOCUMENT WITH (NOLOCK)
WHERE DOC.ord_int_id IN
(
SELECT TPM.ord_int_id FROM TPM_VISIT TPM WITH (NOLOCK)
WHERE TPM300.vst_no = #A
)
END
It throws an error for the first IF Statement
Msg 156, Level 15, State 1, Line 59
Incorrect syntax near the keyword 'IF'.
Not sure what I am doing wrong. Can anyone please guide on how to fix this query.
Thanks in advance.
IF is a procedural statement, not a query clause. From the documentation:
An IF...ELSE construct can be used in batches, in stored procedures, and in ad hoc queries.
You just want regular AND/OR logic e.g.
WHERE (
NULLIF(#A,'') IS NULL
AND DOC.asn_int_id = (
SELECT asn_int_id
FROM TPM
WHERE rec_no = #B
)
)
OR (
NULLIF(#A,'') IS NOT NULL
AND DOC.ord_int_id IN (
SELECT DOC.ord_int_id
FROM TAD_DOCUMENT
WHERE DOC.ord_int_id IN (
SELECT TPM.ord_int_id
FROM TPM_VISIT TPM
WHERE TPM300.vst_no = #A
)
)
)
Note: Unless you are very sure you understand and accept the consequences of using NOLOCK I highly recommend not using it. Its not a "go faster for free" hint.

Error in selecting

I am trying to do a select like this -
SELECT COUNT(*)
FROM
(
DECLARE #Emp varchar(100)
SET #Emp = 'Rick'
SELECT *
FROM [Temporary].[dbo].[Employee_Test]
WHERE [Emp_Name] = #Emp
) AS EMPS
I know that I can fix this by putting the DECLARE statements before outer select. But, due to some crappy design, I would prefer to be able to use the inner query as is and then count the number of rows in it. How do I do that ?
The error I get is -
Msg 156, Level 15, State 1, Line 4
Incorrect syntax near the keyword 'DECLARE'.
Msg 102, Level 15, State 1, Line 9
Incorrect syntax near ')'
DECLARE #Emp varchar(100)
SET #Emp = 'Rick';
SELECT COUNT(*)
FROM [Temporary].[dbo].[Employee_Test]
WHERE [Emp_Name] = #Emp
You need to Declare The variable and SET its values before you pass it to the SELECT Statement. You cannot Declare a Variable Inside a Select Statement.
Should you put a semi-colon after the SET statement?
SET #EMP = 'Rick';

is it posible, create a temp #table inside a openrowset?

i am trying execute this query but i got a error:
Msg 8180, Level 16, State 1, Line 1
Statement(s) could not be prepared.
Msg 208, Level 16, State 1, Line 11
Invalid object name '#test1'.
my code:
select * from openrowset ('SQLOLEDB','DRIVER={SQL Server};SERVER=10.12.131.58;UID=sa;PWD=desarrollo','
create table #test1
(
id int,
name1 varchar(50)
)
insert into #test1
select cliente,nomcli from opepte.dbo.clientes
select * from #test1
/*this is a example but in real query i need manipulate this information and return
a resulset with few rows
*/
')
but this other query works fine.
select * from openrowset ('SQLOLEDB','DRIVER={SQL Server};SERVER=10.12.131.58;UID=sa;PWD=desarrollo','
create table #test1
(
id int,
name1 varchar(50)
)
--insert into #test1
select cliente,nomcli from opepte.dbo.clientes
--select * from #test1
/*this is a example but in real query i need manipulate this information and return
a resulset with few rows
*/
')
Note: insert into #test1 and select * from #test1 are coment
Use FMTONLY & NOCOUNT
Just why not to use tabled-variable instead of temp? Since you are explicitly returns data via this code, nobody will use your temp table again.
Also consider more robust and secure provider and connection string: 'SQLNCLI', 'Server=localhost;Integrated Security=SSPI;Trusted_Connection=yes;'
select * from openrowset ('SQLOLEDB','DRIVER={SQL Server};SERVER=10.12.131.58;UID=sa;PWD=desarrollo', N'
SET FMTONLY OFF
SET NOCOUNT ON
declare #q int = 1
declare #test1 table
(
id int,
name1 varchar(50)
)
insert into #test1
select 1,''q''
insert into #test1
select 1,''q''
select * from #test1
/*this is a example but in real query i need manipulate this information and return
a resulset with few rows
*/
')
I don't think you can as the openquery/rowset interface is quite limited. Given that the remote server is a SQL server you may be able to use a table based function to delivery the functionality you require. Otherwise you could use a remote execution stored procedure or a linked server to do this.

creating a stored procedure from a recursive query

I'd like to create a mssql stored procedure to run a query like the following:
SELECT thingID
FROM things
WHERE thingParentID = #arguments.id#
recursively, accumulating thingIDs in a list which is then returned by the stored procedure.
Does anyone know of a example like this that they can link to? or some documentation that might help me?
Thanks.
This will work on SQL Server 2005 and up.
CREATE FUNCTION dbo.Ancestors (#thingID int)
RETURNS TABLE
AS
RETURN
WITH CTE AS
(
SELECT thingID, 1 [Level]
FROM dbo.things
WHERE thingParentID = #thingID
UNION ALL
SELECT p.thingID, [Level] + 1 [Level]
FROM CTE c
JOIN dbo.things p
ON p.thingParentID = c.thingID
)
SELECT thingID, [Level]
FROM CTE
GO
CREATE PROCEDURE GetAncestors (#thingID int)
AS
SELECT thingID, [Level]
FROM dbo.Ancestors(#thingID)
GO

crux sql if statement problem

Work on ms-server 2005.In my stored procedure i need to use if statement ,I already try to write but i fail ,My syntax is bellow :
Create Procedure TestProcedure
#Type int
as
SELECT * INTO #temp1 FROM (
if #Type =0
select * from dbo.Manifest
else
select * from dbo.DischargePort
) as b
After execute the above syntax show me error message ,Message is
Msg 156, Level 15, State 1, Procedure TestProcedure, Line 8
Incorrect syntax near the keyword 'if'.
Msg 170, Level 15, State 1, Procedure TestProcedure, Line 14
Line 14: Incorrect syntax near ')'.
How to fix the problem,Thanks in advance.
EDIT Ok, so you can't actually insert into #temptable twice because the compiler does not recocgnize that it uses an if statement, the closest workaround was the following:
IF #Type = 0
BEGIN
exec select * into #temp from dbo.Manifest
END
ELSE
BEGIN
select * into #temp from dbo.DischargePort
END
VERSION 2
DECLARE #Type int = 0
IF #Type = 0
exec ('select * into ##temp from dbo.Manifest')
ELSE
exec ('select * into ##temp from dbo.DischargePort')
SELECT * FROM ##temp
And then remember to drop the table at the end
IF (SELECT object_id('TempDB..##temp')) IS NOT NULL
BEGIN
DROP TABLE ##temp
END
And then you would access ##temp like a normal table. Remember that if you want to add parameters to the dynamic sql use sp_exceutesql to avoid sql injection
You remind to drop #temp at the end. Before table creation,you should check if #temp already exists.
IF OBJECT_ID('tempdb..#tmp') IS NOT NULL
DROP TABLE #temp
CREATE TABLE #temp (id int)