Create View dynamically from SP in sql server 2012 - sql

sql server 2012
i have created a SP to create view dynamically with Parameter i supplied.
below is the code
i am not sure why i am getting the below error.
Msg 102, Level 15, State 1, Procedure uspCreateView, Line 10
Incorrect syntax near '#VIEWNM'.
Code:
CREATE PROCEDURE uspCreateView
#VIEWNM VARCHAR(50),
#COMP INT,
#TODT DATE = 9999-12-31
AS
EXEC ('
CREATE VIEW +'#VIEWNM'
AS
(
SELECT
COL1,
COL2,
COL3,
DATE,
SKU,
CASE WHEN IsRowCurrent = 1 THEN '#TODT' ELSE dateadd(MILLISECOND, -1000 - datepart(MILLISECOND, FMDT), FMDT) END AS TODT,
FROM MYTABLE mt
OUTER APPLY ( SELECT MAX(DATEADD(second, -1, FMDT)) TO_DATE
FROM MYTABLE mt2
WHERE mt2.COL1 = mt.COL1
AND mt2.COL2 = mt.COL2
AND mt2.FMDT > mt.FMDT
AND mt.COL3 = '#COMPID' ) oa
WHERE mt.COL3 = '#COMPID'
)
please help me to fix the below error.
Thanks

I am not sure, why you want to create views dynamically, ideally views should be created before hand only, and you will be required to fetch the data depending on the condition.
Still if you want to proceed, you should do it proper way to avoid any issues. I can see there are issues with your implementation. Ideally you should make it parameterized, like following sample query to avoid any SQL injection.
There are issues with your provided code also, I tried to fix some of these.
CREATE PROCEDURE uspCreateView
(
#VIEWNM VARCHAR(50),
#COMP INT,
#TODT DATE = '9999-12-31'
)
AS
BEGIN
DECLARE #Query NVARCHAR(MAX)
DECLARE #ParmDefinition nvarchar(MAX);
SET #Query = N'CREATE VIEW #VIEWNM_I AS ( SELECT COL1, COL2, COL3, DATE, SKU,
CASE WHEN IsRowCurrent = 1 THEN #TODT_I ELSE
dateadd(MILLISECOND, -1000 - datepart(MILLISECOND, FMDT)
, FMDT) END AS TODT, FROM MYTABLE mt OUTER APPLY (
SELECT MAX(DATEADD(second, -1, FMDT)) TO_DATE
FROM MYTABLE mt2
WHERE mt2.COL1 = mt.COL1
AND mt2.COL2 = mt.COL2
AND mt2.FMDT > mt.FMDT
AND mt.COL3 = #COMPID_I ) oa
WHERE mt.COL3 = #COMPID_I)'
SET #ParmDefinition = N'#VIEWNM VARCHAR(100),#TODT_I DATETIME,#COMP_I INT';
EXECUTE sp_executesql #Query,#ParmDefinition, #VIEWNM_I=#VIEWNM, #COMP_I=#COMP, #TODT_I=#TODT
END

Try this
Command(s) completed successfully.
CREATE PROCEDURE uspCreateView
#VIEWNM VARCHAR(50),
#COMP INT,
#TODT DATE = '9999-12-31'
AS
EXEC ('
CREATE VIEW '+#VIEWNM+'
AS
(
SELECT
COL1,
COL2,
COL3,
DATE,
SKU,
CASE WHEN IsRowCurrent = 1 THEN '+#TODT+' ELSE dateadd(MILLISECOND, -1000 - datepart(MILLISECOND, FMDT), FMDT) END AS TODT,
FROM MYTABLE mt
OUTER APPLY ( SELECT MAX(DATEADD(second, -1, FMDT)) TO_DATE
FROM MYTABLE mt2
WHERE mt2.COL1 = mt.COL1
AND mt2.COL2 = mt.COL2
AND mt2.FMDT > mt.FMDT
AND mt.COL3 = '+#COMP+' ) oa
WHERE mt.COL3 = '+#COMP+'
) ')

It should be
CREATE VIEW ' + #VIEWNM + ' AS...

Related

Error creating function with temporary tables

I am creating a function that contains a temporary table, it is a bit difficult for me to use the function with a temporary table, I totally do not know if it is allowed within a function since I am new to the new one.
The function I am trying to create is the following:
CREATE FUNCTION FunctionTest (
#Anio int=null,
#Mes int=Null,
#Meses int=6
)
RETURNS #Tabla TABLE (
AnioMes INT,
Viaje VARCHAR(30),
IdPorte INT,
Carga VARCHAR(20),
Peso numeric(32, 16)
)
AS
BEGIN
Declare #AnioMes varchar(8),
#AnioMes6 varchar(8)
if #Anio is null
Select #Anio = YEAR(GETDATE()),
#Mes = MONTH(GETDATE())
Select #AnioMes = (case when #Mes=12 then #Anio+1 else #Anio end *100 + Case when #Mes=12 then 1 else #Mes+1 end)*100 + 1
Select #AnioMes6 = convert(varchar(8), DATEADD(mm, -#Meses, #AnioMes), 112 )
INSERT INTO #Tabla (AnioMes,Viaje,IdPorte,Carga,Peso)
SELECT year(cpsj.Delivery)*100 + MONTH(cpsj.Delivery) as AnioMes,
tr.TId as Viaje,
cpsj.PId as IdPorte,
CASE WHEN tr.Load = 1 THEN 'CARGADO'
WHEN tr.Load = 2 THEN 'VACIO'
END as Carga,
cpsj.Weight as Peso,
into #Temp
FROM BDNEW.dbo.CENPACKSTOREJOIN cpsj
inner join TRANS tr on cpsj.ipId = tr.ipId
inner join OPERA oper on tr.OId = oper.OId
WHERE cpsj.Id = 'ID001'
AND tr.Area = 'lost'
AND tr.Status = 2
GROUP BY cpsj.Delivery, cpsj.IName
ORDER BY cpsj.ipId
if #AnioMes6 < '20160101'
insert #Temp
SELECT Year(cpsj.Delivery)*100 + MONTH(cpsj.Delivery) as AnioMes,
tr.TId as Viaje,
cpsj.PId as IdPorte,
CASE WHEN tr.Load = 1 THEN 'CARGADO'
WHEN tr.Load = 2 THEN 'VACIO'
END as Carga,
cpsj.Weight as Peso,
FROM BDOLD.dbo.CENPACKSTOREJOIN cpsj
inner join TRANS tr on cpsj.ipId = tr.ipId
inner join OPERA oper on tr.OId = oper.OId
WHERE cpsj.Id = 'ID001'
AND tr.Area = 'lost'
AND tr.Status = 2
GROUP BY cpsj.Delivery, cpsj.IName
ORDER BY cpsj.ipId
Delete #Temp
where viaje in (
select MAX(Viaje)
from #Temp
group by IdPorte
having COUNT(IdPorte) > 1
)
Select AnioMes,
Viaje,
IdPorte,
Carga,
Peso,
from #Temp
GROUP BY AnioMes,IdPorte Viaje, Carga, Peso
ORDER BY AnioMes,IdPorte
RETURN
END
If you notice I am making use of a temporary table called #Temp.
As an error message when trying to compile the function I get the following error message:
Cannot access temporary tables from within a function.
That is why I mentioned earlier if you can really make use of temporary tables in a function.
I appreciate anyone who can give me guidance on how to handle this function.
You either use
INSERT INTO #Tabla (AnioMes,Viaje,IdPorte,Carga,Peso)
SELECT year(cpsj.Delivery)*100 ...
Or
SELECT year(cpsj.Delivery)*100 ...
INTO #Temp
FROM...
Not both:
INSERT INTO #Tabla (AnioMes,Viaje,IdPorte,Carga,Peso)
SELECT year(cpsj.Delivery)*100 ...
INTO #Temp
FROM...
And also you can't use temp tables in functions.

Parameter Sniffing Not working

I am using MSSQL. I have a stored procedure which works fine for couple of days and later on it becomes slow. I came to know that Parameter Sniffing will work for it. How ever after implementing it it became slow for ever. I also tried to Recompiling job. I faced the same slowness issue immediately.
Can some one please help me with this ?
Below is the structure of my Stored Procedure.
#START_VALUE int=null,
#END_VALUE int=null
#UID NVARCHAR(MAX)=null,
AS
BEGIN
SELECT
dbo.TABLE1.ID,
ROW_NUMBER() OVER (ORDER BY TABLE1.UPDATED_ON desc) AS RN,
CONVERT(VARCHAR(10), dbo.TABLE1.DATE, 101) AS TDATE,
CATEGORY = (
SELECT TOP 1 COLUMN1
FROM TABLE5 CT1
WHERE TABLE1.CATEGORY = CT1.CATEGORY_ID
),
TYPETEXT = (
SELECT TOP 1 COLUMN1
FROM TABLE6 CT1
WHERE TABLE1.TYPE = CT1.TYPE_ID
),
IMAGE = STUFF(( SELECT DISTINCT ',' + CAST(pm.C1 AS varchar(12))
FROM TABLE2 pm
WHERE pm.ID = TABLE1.ID AND pm.C1 IS NOT NULL AND pm.C1 <> ''
FOR XML PATH('')),
1, 1, '' ) INTO #tempRecords
FROM dbo.TABLE1
WHERE ((#UID is null OR dbo.TABLE1.ID = #UID )
ORDER BY TABLE1.UPDATED DESC
SELECT #count = COUNT(*) FROM #tempRecords;
SELECT *, CONVERT([int],#count) AS 'TOTAL_RECORDS'
FROM #tempRecords
WHERE #tempRecords.RN BETWEEN CONVERT([bigint], #START_VALUE) AND CONVERT([bigint], #END_VALUE)
END
GO
To make the query optimized for parameter sniffing, declare dummy variables and use them in your query, as opposed to using the original parameters as such.
CREATE PROCEDURE test_proc
#START_VALUE INT=NULL,
#END_VALUE INT=NULL,
#UID NVARCHAR(max)=NULL
as
BEGIN
DECLARE #START_VALUE_SNIFF INT=NULL,
#END_VALUE_SNIFF INT=NULL,
#UID_SNIFF NVARCHAR(max)=NULL
SET #START_VALUE_SNIFF = #START_VALUE
SET #END_VALUE_SNIFF = #END_VALUE
SET #UID_SNIFF = #UID
select * from
FROM dbo.TABLE1
WHERE ((#UID_SNIFF is null OR dbo.TABLE1.ID = #UID_SNIFF )
ORDER BY TABLE1.UPDATED DESC
END

Stored procedure becomes slow every couple of days

I am facing an issue on SQL Server in which my stored procedure becomes slow after couple of days.
Below is the sample of my stored procedure.
Could this be a caching issue on the server side? Can I increase the server's cache size to resolve the problem?
Normally the stored procedure returns data in one second.
#START_VALUE int=null,
#END_VALUE int=null
#UID NVARCHAR(MAX)=null,
AS
BEGIN
SELECT
dbo.TABLE1.ID,
ROW_NUMBER() OVER (ORDER BY TABLE1.UPDATED_ON desc) AS RN,
CONVERT(VARCHAR(10), dbo.TABLE1.DATE, 101) AS TDATE,
CATEGORY = (
SELECT TOP 1 COLUMN1
FROM TABLE5 CT1
WHERE TABLE1.CATEGORY = CT1.CATEGORY_ID
),
TYPETEXT = (
SELECT TOP 1 COLUMN1
FROM TABLE6 CT1
WHERE TABLE1.TYPE = CT1.TYPE_ID
),
IMAGE = STUFF(( SELECT DISTINCT ',' + CAST(pm.C1 AS varchar(12))
FROM TABLE2 pm
WHERE pm.ID = TABLE1.ID AND pm.C1 IS NOT NULL AND pm.C1 <> ''
FOR XML PATH('')),
1, 1, '' ) INTO #tempRecords
FROM dbo.TABLE1
WHERE ((#UID is null OR dbo.TABLE1.ID = #UID )
ORDER BY TABLE1.UPDATED DESC
SELECT #count = COUNT(*) FROM #tempRecords;
SELECT *, CONVERT([int],#count) AS 'TOTAL_RECORDS'
FROM #tempRecords
WHERE #tempRecords.RN BETWEEN CONVERT([bigint], #START_VALUE) AND CONVERT([bigint], #END_VALUE)
END
GO
'
A few performance tips:
1) #UID is null OR dbo.TABLE1.ID = #UID --> this is bad because you'll have one execution plan when UID is null and when it's not. Build a dynamic sql query and you'll get 2 execution plans.
2) Update stats in a maintenance plan.
3) Check index fragmentation.
4) Try to do the same thing without using a temp table.
5) Try to avoid castings.

SQL Return to front end

I have the following SQL Server stored procedure and when this is called by the front end code it returns the return value which is 0 instead of select of total count. can any one tell me what changes do i need to do to make it return the select values instead of return value
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[getTotalSent1]
(
#vendorworksationID uniqueidentifier ,
#sdate date,
#edate date
)
as
begin
select
camp.totalSent + bcamp.totalSent as totalSent
from
(select
COUNT(*) as totalSent
from
AdvertisedCampaignHistory a
where
CAST(a.CreationDate AS DATE) BETWEEN CAST(#sdate as DATE) AND CAST(#edate as DATE)
and a.CampaignID in (select cc.CampaignID
from campaign cc, VendorWorkStation vw
where cc.VendorWorkStationID = vw.VendorWorkStationID
and VendorID = #vendorworksationID)) as camp
join
(select
COUNT(*) as totalSent
from
AdvertisedCampaignHistory a
where
CAST(a.CreationDate AS DATE) BETWEEN CAST(#sdate as DATE) AND CAST(#edate as DATE)
and a.CampaignID in (select bc.BCampaignID
from BeaconCampaign bc, VendorWorkStation vw
where bc.VendorWorkStationID = vw.VendorWorkStationID
and VendorID = #vendorworksationID)) as bcamp on 1=1
end
Output:
Totalsent
---------
240
return
-----
0
It's returning 0, I want total sent value
CREATE PROCEDURE getTotalSent1
AS
DECLARE #TotalSent int
-- Do some work here
SELECT #TotalSent = 240
RETURN #TotalSent
GO
-- EXEC CODE
DECLARE #totalsent int
EXEC #totalsent = dbo.getTotalSent1
SELECT #totalsent as totalSent
ALTER procedure [dbo].[getTotalSent1]
(
#vendorworksationID uniqueidentifier ,
#sdate date,
#edate date
#total_set int output
)
as
`enter code here`
return
get param like this
declare #got_it int
exec [dbo].[getTotalSent1] xxx,yyy,#total_set=#got_it output
`
Try this:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[getTotalSent1]
(
#vendorworksationID uniqueidentifier ,
#sdate date,
#edate date
)
as
begin
DECLARE #totalSent INT
select
#totalSent =camp.totalSent + bcamp.totalSent
from
(select
COUNT(*) as totalSent
from
AdvertisedCampaignHistory a
where
CAST(a.CreationDate AS DATE) BETWEEN CAST(#sdate as DATE) AND CAST(#edate as DATE)
and a.CampaignID in (select cc.CampaignID
from campaign cc, VendorWorkStation vw
where cc.VendorWorkStationID = vw.VendorWorkStationID
and VendorID = #vendorworksationID)) as camp
join
(select
COUNT(*) as totalSent
from
AdvertisedCampaignHistory a
where
CAST(a.CreationDate AS DATE) BETWEEN CAST(#sdate as DATE) AND CAST(#edate as DATE)
and a.CampaignID in (select bc.BCampaignID
from BeaconCampaign bc, VendorWorkStation vw
where bc.VendorWorkStationID = vw.VendorWorkStationID
and VendorID = #vendorworksationID)) as bcamp on 1=1
return #totalSent
end
After BEGIN type SET NOCOUNT ON;
This disables the default return value for stored procedures, so that you get the results of your query instead.
And as a side note, you need to replace your proprietary joins with the ANSI equivalent...
e.g.
...
FROM tblA a
JOIN tblB b
ON a.key = b.key
It's better to avoid doing the join in the WHERE clause.

Sql server exception: the statement did not return a result set

I have a SQL query that runs fine in SQL Server Management Studio, but when I copy and paste it into jasperreports's iReport to make a report, it gives me a SQL Server exception and says the statement did not return a result set. This has left me confused.
The query is:
declare #index int = 1
declare #t Table(ID INT, DI INT, INDBOOK1 INT, INDBOOK2 INT, delta INT)
while(#index < 18)
begin
INSERT INTO #t
select distinct top 18
col1.ID,
col1.DI,
col1.INDBOOK as INDBOOK1,
col2.INDBOOK as INDBOOK2,
col2.INDBOOK - col1.INDBOOK
FROM
table as col1
inner join
table as col2 on col2.ID = #index
and col2.DI = col1.DI+1
where
col1.ID = #index
set #index = #index + 1
end
select ID, DI, INDBOOK1, INDBOOK2, delta FROM #t
Does anybody know why this is giving me the no result set returned exception?
Any help appreciated.
Tough to tell without sample data etc. but I think this should be close to what you need, in a single statement with no explicit loops:
;WITH x([index]) AS
(
SELECT TOP (18) ROW_NUMBER() OVER (ORDER BY number)
FROM master..spt_values ORDER BY number
),
y AS
(
SELECT [index] = ROW_NUMBER() OVER (PARTITION BY col1.ID ORDER BY col1.ID),
col1.ID, col1.DI, col1.INDBOOK as INDBOOK1, col2.INDBOOK as INDBOOK2,
col2.INDBOOK - col1.INDBOOK as delta
FROM dbo.table as col1
INNER JOIN dbo.table as col2
ON col2.ID = col1.ID
AND col2.DI = col1.DI+1
)
SELECT y.ID, y.DI, y.INDBOOK1, y.INDBOOK2, y.delta
FROM x INNER JOIN y
ON x.[index] = y.[index]
WHERE y.[index] <= 18;