crux sql if statement problem - sql

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)

Related

select into a table using a variable as table name dynamic sql not working

I'm trying to execute the code below (I know a lot of people have already asked this question but none of them worked for me). since I have a loop I need to select into multiple new tables with the value of variable name as tables names.
I tried using dynamic sql for the tables name like this:
WHILE ( #Counter <= #len)
begin
DECLARE #name VARCHAR(10),#sql nvarchar(max)
SET #name= (select product from #ProductType where NewPK= #Counter)
set #sql='
select m=DATEPART(month,t2.initial_date),y=DATEPART(year,t2.initial_date) ,t1.user_orders,t1.account_id
into '+#name+'
from (select dbo.sales_info.account_id, count(*) as user_orders
from dbo.sales_info
where dbo.sales_info.product= #name
group by dbo.sales_info.account_id) t1
left join
(select dbo.sales_info.account_id, initial_date= min( dbo.sales_info.start_date)
from dbo.sales_info group by dbo.sales_info.start_date,dbo.sales_info.account_id )t2
on t1.account_id=t2.account_id
order by m,y'
exec (#sql)
SET #Counter = #Counter + 1
end
but I keep getting this error :
Must declare the scalar variable "#name".
Msg 102, Level 15, State 1, Line 10
Incorrect syntax near 't2'.
Msg 137, Level 15, State 2, Line 6
Must declare the scalar variable "#name".
Msg 102, Level 15, State 1, Line 10
Incorrect syntax near 't2'.
The problem is this line of code:
where dbo.sales_info.product = #name
You can use parameters when you execute the code:
exec sp_executesql #sql,
N'#name varchar(10),
#name=#name;

Syntax error using multiple CTEs

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

use a "temporary table" and "while loop" together in sql

I want to create a table and after that use the table information in a while loop. I had been used 'with' to create the table but my code has error. The code comes below:
declare #i integer
set #i=0;
with cte as
(SELECT ROW_NUMBER()OVER(ORDER BY ItemID) as RowNumber,*,DATEDIFF(day,GETDATE(),AdDateTo)as DaysToExpire
FROM KenticoCMS1.dbo.AD_Advertise inner join KenticoCMS1.dbo.CMS_User
ON KenticoCMS1.dbo.AD_Advertise.ItemCreatedBy = KenticoCMS1.dbo.CMS_User.UserID
WHERE DATEDIFF(day,GETDATE(),AdDateTo) in (SELECT RemainDays FROM KenticoCMS1.dbo.AD_SendEmailForExpire)
AND AdShow=1)
--SELECT * FROM cte
while ( #i<=(select max(RowNumber) from cte))
BEGIN
#i=#i+1;
EXEC msdb.dbo.sp_send_dbmail #profile_name='ExpireAdvertiseEmail',
#recipients= select Email FROM cte where RowNumber=#i , --'mj.yazdani1988#gmail.com',
#subject='Test message',
#body='This is the body of the test message.Congrates Database Mail Received By you Successfully.'
END
GO
and my error:
Msg 156, Level 15, State 1, Line 13
Incorrect syntax near the keyword 'while'.
Msg 156, Level 15, State 1, Line 16
Incorrect syntax near the keyword 'select'.
Msg 102, Level 15, State 1, Line 16
Incorrect syntax near ','.
You cannot use CTE as temporary table. You could create table (or declare table variable), put your data there and do your work:
create table #temp (RowNumber int, Email nvarchar(max)
But so far looks like your code could be changed like this:
declare #Email nvarchar(max)
declare cur cursor local fast_forward for
select
u.Email
from KenticoCMS1.dbo.AD_Advertise as a
inner join KenticoCMS1.dbo.CMS_User as u on u.UserID = a.ItemCreatedBy
where
a.AdShow = 1 and
datediff(day, getdate(), a.AdDateTo) in
(
select t.RemainDays
from KenticoCMS1.dbo.AD_SendEmailForExpire as t
)
open cur
while 1 = 1
begin
fetch cur into #Email
if ##fetch_status <> 0 break
exec msdb.dbo.sp_send_dbmail
#profile_name = 'ExpireAdvertiseEmail',
#recipients = #Email,
#subject = 'Test message',
#body = 'This is the body of the test message.Congrates Database Mail Received By you Successfully.'
end
close cur
deallocate cur
Note table aliases, removing redundant brackets. I think it'll also helps to remove datediff, but have to see your data before.
try this: put this part
while ( #i<=(select max(RowNumber) from cte))
BEGIN
#i=#i+1;
EXEC msdb.dbo.sp_send_dbmail #profile_name='ExpireAdvertiseEmail',
#recipients= (
before
with cte as
and a
)
after
...where RowNumber=#i
for my understanding the cte definition must be followed directly by select (and it can be used in only that one select that follows)
hope it helps...
EDIT: commas obviously part of parameterlist for function

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.

T-SQL error object exists when separated in if/else blocks

I get the error: Msg 2714, Level 16, State 1, Line 16
There is already an object named '#mytemptable' in the database.
There are ways around it, but wonder why this happens. Seems like SQL Server is verifying both blocks of the if/else statement?
declare #choice int
select #choice = 1
if #choice = 1
begin
select 'MyValue = 1' AS Pick into #my_temp_table
end
else
begin
select 'MyValue <> 1' AS Pick into #my_temp_table
end
select * from #my_temp_table
drop table #my_temp_table
If the tables have different names, it works. Or if I create the temp table and use Insert Into... statements that works as well.
See here: What is deferred name resolution and why do you need to care?
basically you need to ceate the table first
So what is happening is that beginning with SQL server 7 deferred name resolution was enabled for real tables but not for temporary tables. If you change the code to use a real table instead of a temporary table you won’t have any problem
Here is another way
declare #choice int
select #choice = 1
declare #Value varchar(100)
if #choice = 1
select #Value = 'MyValue = 1'
else
select #Value = 'MyValue <> 1'
select #Value AS Pick into #my_temp_table
select * from #my_temp_table
drop table #my_temp_table
Try this:
declare #choice int
select #choice = 1
CREATE TABLE #my_temp_table(
Pick varchar(25)
)
if #choice = 1
begin
INSERT INTO #my_temp_table
select 'MyValue = 1'
end
else
begin
INSERT INTO #my_temp_table
select 'MyValue <> 1'
end
select * from #temptable
drop table #temptable
EDIT Sorry, I see that you tried this and the question was WHY does this happen. It is because SQL Server parses the stored procedure when it is created and checks for naming conflicts.