Explicit command work, while its TSQL equivalent throws an error - sql

Error:
Could not find stored procedure 'SELECT TOP 1 name FROM (SELECT TOP 5 name FROM sys.tables ORDER BY name DESC) as t ORDER BY name ASC'.
Code:
WHILE (#interval <= #max)
BEGIN
SET #SQL = 'SELECT TOP 1 name FROM (' +
SELECT TOP ' + convert(varchar(10), #interval) +
' name FROM sys.tables ORDER BY name DESC) as t ORDER BY name ASC'
EXEC #SQL
SELECT #interval = #interval + 1
END
Executing the following command on its own works properly:
SELECT TOP 1 name
FROM
(SELECT TOP 5 name
FROM sys.tables
ORDER BY name DESC) as t
ORDER BY
name ASC
Incrementing the inner TOP # manually and running the command without TSQL will rotate through each table properly. (This will eventually include a nested loop for Column, and another nested loop for a search within that column.)
That the command runs without the variable makes me think this is a scope issue. Shouldn't I be able to resolve this by inserting the list of table names into a temp table with a Primary Key of Seed 1, Increment 1 for a row_id, and then looping through the table via incrementing my #row_id = row_id?
Any suggestions?

It should be exec(#sql), I think

Related

SQL Server 2008 R2 : Conversion failed when converting date and/or time from character string

I'm getting the following error
Conversion failed when converting date and/or time from character string
I can't get it to run properly please help me, here is my code (don't shame my loop i just need it to work).
The thing is i have a closed list with contracts IDs and a table with different dates and dates called #PERIODO it contains datetime type.
WHILE (SELECT TOP 1 FECHA1 FROM #PERIODO) > 0
BEGIN
SET #MES_ANTERIOR = (SELECT TOP 1 FECHA1 FROM #PERIODO ORDER BY FECHA1 ASC)
SET #MES_EN_CURSO = (SELECT TOP 1 B.FECHA1 FROM (SELECT TOP 2 A.FECHA1 FROM #PERIODO A ORDER BY FECHA1 ASC ) B ORDER BY B.FECHA1 DESC)
SET #MES_3 = (SELECT TOP 1 FECHA3 FROM #PERIODO ORDER BY FECHA1 ASC)
SET #MES_4 = (SELECT TOP 1 B.FECHA3 FROM (SELECT TOP 2 A.FECHA3 FROM #PERIODO A ORDER BY FECHA3 ASC ) B ORDER BY B.FECHA3 DESC)
SET #MES_ANT = LEFT(CONVERT(VARCHAR(8),#MES_ANTERIOR,112),8) -- SELECT #MES_ANT
SET #MES_CURR = LEFT(CONVERT(VARCHAR(8),#MES_EN_CURSO,112),8) -- SELECT #MES_CURR
EXEC('IF OBJECT_ID(''WORK.DBO.OPERACIONES_ABIF_'+#MES_CURR+''', ''U'') IS NOT NULL
DROP TABLE WORK.DBO.OPERACIONES_ABIF_'+#MES_CURR+' ')
SET #SQL1 = 'SELECT DISTINCT
A.*
INTO WORK.DBO.OPERACIONES_ABIF_'+#MES_CURR+'
FROM BDGESTION.DBO.BASE_RIESGOS_PROD_ALTAIR_'+#MES_CURR+' A WHERE '
SET #SQL2 = ' A.NUM_OPERACION IN (
SELECT
B.NUM_CONTRATO
FROM (
SELECT NUM_CONTRATO
FROM
( SELECT * FROM #OPER WHERE FECHA_INICIO IS NOT NULL) H
WHERE H.FECHA_INICIO < CAST(CONVERT(VARCHAR(12),'+#MES_EN_CURSO+',23) AS VARCHAR )
AND H.FECHA_INICIO >= CAST(CONVERT(VARCHAR(12),'+#MES_ANTERIOR+',23) AS VARCHAR )
) B
WHERE
B.NUM_CONTRATO IS NOT NULL ) '
EXEC (#SQL1 + #SQL2)
DELETE FROM #PERIODO
WHERE FECHA1 = #MES_ANTERIOR
END
The problem would appear to be these lines:
WHERE H.FECHA_INICIO < CAST(CONVERT(VARCHAR(12), ' + #MES_EN_CURSO + ', 23) AS VARCHAR)
Presumably, you want the cast() outside the aggregation:
WHERE H.FECHA_INICIO < ' + CONVERT(VARCHAR(12), #MES_EN_CURSO + ', 23) + '
However, I don't recommend this as a solution. The correct solution is to pass the value in as a parameter. Your query is too complex (and messy) for me to attempt that. You should look at the documentation for sp_executesql on how to properly construct dynamic SQL with parameters.
I think you should print #SQL2 as you go through the loop so you can see the incorrect value.
It would be helpful to show how you declare #MES_EN_CURSO and declare #MES_ANTERIOR.

How to create stored procedure with view?

I tried to execute this code and it worked o.k without the the stored procedure and with it, it made an error.
The error is:
Msg 102, Level 15, State 1, Procedure UV_MTBF, Line 251
Incorrect syntax near 'Event_'.
Is the stored procedure have a limitation in length?
can someone help me with my code?
edit*
my problem is with ' + QUOTENAME(#category,N'''') + N'
i want to add an integer from a variable that i received in the stored procedure. how can i do it?
enter code here:
CREATE PROCEDURE dbo.MTBFCalculation #Category int, #Action bit, #relateToParent bit
as
IF EXISTS (SELECT 1 FROM sys.objects WHERE [name] = '[dbo].[UV_MTBF]')
DROP VIEW [dbo].[UV_MTBF];
DECLARE #Event nvarchar(MAX) = N'
CREATE VIEW [dbo].[UV_MTBF]
as
with failureReportTable as (SELECT [ID] as failure_id
,[Login_ID]
,[Event_ID]
,[StartDate]
,[EndDate]
,DATEDIFF(Hour,[StartDate],[EndDate]) as eventDurationMin
,[IsRelevantForBI]
,[IsParallelReport]
,[ParentReportID]
,[IsPausedEvent]
,Case
When ParentReportID>0 Then 1 --Chiled
When IsParallelReport=1 Then 2 --Parent
Else 3 --not Parallel
End as ParallelStatus
FROM [TDM_Analysis].[dbo].[FailureReports]),
fullFailure as (select *, ROW_NUMBER() OVER (ORDER BY [StartDate] ) AS IDrow
from failureReportTable join [TDM_Analysis].[dbo].[UV_filteredLogins] as viewLogins on failureReportTable.Login_ID=viewLogins.ID
WHERE event_id IN (SELECT ID FROM [TDM_Analysis].[dbo].[Events] where EventCategory_ID=' + QUOTENAME(#category,N'''') + N')
and (ParallelStatus=3 or ParallelStatus=(case when ' + QUOTENAME(#relateToParent,N'''') + N'=1 then 2 else 1 end))),
--------------create first failure table------------------
failure_Event_1 as (select f1.failure_id as Event_1_Failure_ID
,f1.[Login_ID] as Event_1_Login_ID
,f1.[Event_ID] as Event_1_Event_ID
,f1.[StartDate] as Event_1_StartDate
,f1.[EndDate] as Event_1_EndDate
,f1.eventDurationMin as Event_1_eventDurationMin
--,f1.[IsRelevantForBI] as Event_1_IsRelevantForBI
--,f1.[IsParallelReport] as Event_1_IsParallelReport
-- ,f1.[ParentReportID] as Event_1_ParentReportID
-- ,f1.[IsPausedEvent] as Event_1_IsPausedEvent
,f1.[Test_Name] as Event_1_TestName
,f1.Phase_Name as Event_1_PhaseName
,f1.PressName as Event_1_PressName
,f1.PressType as Event_1_PressType
--,f1.[Operator] as Event_1_Operator
,f1.[LoginDate] as Event_1_LoginDate
,f1.[LogoutDate] as Event_1_LogoutDate
,f1.TimeDiff as Event_1_LoginDuration
,f1.IDrow+1 as row1
from fullFailure as f1),
--------------create second failure table------------------
failure_Event_2 as (select f1.failure_id as Event_2_Failure_ID
,f1.[Login_ID] as Event_2_Login_ID
,f1.[Event_ID] as Event_2_Event_ID
,f1.[StartDate] as Event_2_StartDate
,f1.[EndDate] as Event_2_EndDate
,f1.eventDurationMin as Event_2_eventDurationMin
-- ,f1.[IsRelevantForBI] as Event_2_IsRelevantForBI
-- ,f1.[IsParallelReport] as Event_2_IsParallelReport
-- ,f1.[ParentReportID] as Event_2_ParentReportID
-- ,f1.[IsPausedEvent] as Event_2_IsPausedEvent
,f1.[Test_Name] as Event_2_TestName
,f1.Phase_Name as Event_2_PhaseName
,f1.PressName as Event_2_PressName
,f1.PressType as Event_2_PressType
-- ,f1.[Operator] as Event_2_Operator
,f1.[LoginDate] as Event_2_LoginDate
,f1.[LogoutDate] as Event_2_LogoutDate
,f1.TimeDiff as Event_2_LoginDuration
,f1.IDrow as row2
from fullFailure as f1),
------------- join two failure tabels and calculating MTTR-mean time to repair (duration of failue), MTTF-mean time to failue( end of one until start of a new one), MTBF-mean time between failue (from start of a failure to start of a new one)--------------------
joinFailures as (select *, Event_1_eventDurationMin as MTTR
,CASE
When isnull(f2.row2,0)=0 then DATEDIFF(HOUR,f1.Event_1_EndDate,f1.Event_1_LogoutDate)
WHEN f1.Event_1_Login_ID=f2.Event_2_Login_ID THEN DATEDIFF(HOUR,f1.Event_1_EndDate,f2.Event_2_StartDate)
When (select TOP 1 sum(timediff)
from [TDM_Analysis].[dbo].[UV_filteredLogins]
where logindate>f1.Event_1_LogoutDate and logindate<f2.Event_2_LoginDate) is null then DATEDIFF(HOUR,f1.Event_1_EndDate,f1.Event_1_LogoutDate)+DATEDIFF(HOUR,f2.Event_2_LoginDate, f2.Event_2_StartDate)
ELSE
(select TOP 1 sum(timediff)+DATEDIFF(HOUR,f1.Event_1_EndDate,f1.Event_1_LogoutDate)+DATEDIFF(HOUR,f2.Event_2_LoginDate, f2.Event_2_StartDate)
from [TDM_Analysis].[dbo].[UV_filteredLogins]
where logindate>f1.Event_1_LogoutDate and logindate<f2.Event_2_LoginDate)
END AS MTTF
from failure_Event_1 as f1 left join failure_Event_2 as f2 on f1.row1=f2.row2),
positiveJoinFailure as (select * from joinFailures where MTTF>=0)
---- select calculation table order by ascending time----------
select * --Event_1_Failure_ID,Event_2_Failure_ID,MTTR,MTTF, MTTR+MTTF as MTFB
from positiveJoinFailure
--order by row1
';
--------------------------------------------------------Action------------------------------------------------------------------------------
if #Action=1
begin
EXEC sp_executesql #Event;
end
for this part of your query
where EventCategory_ID=' + QUOTENAME(#category,N'''') + N')
2 option here, you convert the value of #category to string and then concatenate with the dynamic query
where EventCategory_ID=' + convert(varchar(10), #category)
OR, you pass the value in as a parameter.
for this option, you specify #category in the dynamic query
where EventCategory_ID= #category
and (ParallelStatus=3 ....
and you pass the value in at sp_executesql
EXEC sp_executesql #Event, N'#category int', #category
By the way, Option 2 is the preferred method when using dynamic query

Using SQL Table Value for From Clause

I'm trying to write a SQL script which pulls the value of a cell in a given table across multiple databases in a single server. The table has the same name and path across several databases. I'd like to list the specific cell values in a new table.
My first step is to pull all of the database names into a temporary table and then concatenate the table path to it. The code I use is
SELECT name
INTO #dbtablepaths
FROM master.dbo.sysdatabases
WHERE name like 'FTR[0-9]%'
UPDATE #dbtablepaths
SET name=CONCAT(name, '.ftrdbo.[File]')
This will create a table of dbo paths that when queried will return the following:
__|__name_____________
1 | FTR108547.ftrdbo.[File]
2 | FTR564187.ftrdbo.[File]
3 | FTR849721.ftrdbo.[File]
I can then pull one of these dbo paths using the following query
SELECT name FROM(
SELECT ROW_NUMBER() OVER (ORDER BY name ASC) as rownumber,
name
FROM #dbtablepaths
) AS foo
WHERE rownumber = 1
This will return the first dbo path in the table which is FTR108547.ftrdbo.[File].
If I simply copy that path into a SELECT statement (see below) it will bring up the table as intended.
SELECT * FROM FTR108547.ftrdbo.[File]
However, if I try to use a subquery to enter that into the FROM clause of a SELECT statement then the query simply returns the dbo path again. E.G.
SELECT * FROM (
SELECT name FROM(
SELECT ROW_NUMBER() OVER (ORDER BY name ASC) as rownumber,
name
FROM #dbtablepaths
) AS foo
WHERE rownumber = 1
)
I would expect this query to pull the File table but instead it just returns the dbo path again. I.E. FTR108547.ftrdbo.[File]
Is there a way to use table cell values to create queries like this? I know the SELECT statement is returning a table and not a string. Is there a way to convert this table value to a string that can be used in a subsequent SELECT query?
you will have to forgive me as i am unable to make comments yet but you will probally want to take a look at the answers in this post
Executing SQL query on multiple databases
it has several examples that will work for you
This will assign the result into a variable #tabname and use it in the SELECT
DECLARE #sql VARCHAR(MAX)
DECLARE #tabname VARCHAR(100)
SELECT name
INTO #dbtablepaths
FROM master.dbo.sysdatabases
WHERE name like 'FTR[0-9]%'
UPDATE #dbtablepaths
SET name=CONCAT(name, '.ftrdbo.[File]')
SELECT #tabname = name
FROM (SELECT ROW_NUMBER() OVER (ORDER BY name ASC) AS rownumber,
name
FROM #dbtablepaths
) AS foo
WHERE rownumber = 1
SET #sql = 'SELECT * FROM ' + #tabname
EXEC(#sql)

SQL Feed Query results into Union All Statement

I have a COTS application database that creates a new table every week that follows a specific naming convention and always contains the same columns. I have written a query to select the tables within a certain time range:
DECLARE #today VARCHAR(8)
SET #today = CONVERT(VARCHAR(8),GETDATE(),112)
DECLARE #monthold VARCHAR(8)
SET #monthold = CONVERT(VARCHAR(8),dateadd(day,-31,#today),112)
SELECT name
FROM sys.tables
WHERE name <= 'Event_Audit'+ #today AND name >= 'Event_Audit'+ #monthold
AND name like 'Event_Audit%'
ORDER BY name DESC
Now I am looking for a way to have a query call each of the tables that is selected to aggregate the data. This will be used for SSRS reporting.
Something like this where table1, table2, etc. through all the included tables will get populated (whether it is 4, 5, or more):
SELECT *
FROM table1
UNION ALL
SELECT *
FROM table2
UNION ALL
...
ORDER BY EVENT_DATE DESC
I can't create views, new tables, or make any changes to existing tables.
Poor design will lead to hard work every time, this one is no exception. I'm guessing by now it's too late to give up the idea of creating the same table over and over again for each month.
You do not need to create a new or temporary table to execute sp_executeSql, you only need to generate the sql script:
DECLARE #today char(8) = CONVERT(char(8),GETDATE(),112),
#monthold char(8) = CONVERT(char(8),dateadd(day,-31,GETDATE()),112),
#sql nvarchar(max) = ''
SELECT #Sql = #Sql + ' UNION ALL SELECT * FROM ' + name
FROM sys.tables
WHERE name <= 'Event_Audit'+ #today AND name >= 'Event_Audit'+ #monthold
AND name like 'Event_Audit%'
ORDER BY name DESC
SET #SQL = STUFF(#SQL, 1, 11, '') + -- remove the first UNION ALL
' ORDER BY EVENT_DATE DESC' -- add the ORDER BY
PRINT #Sql
--EXEC sp_executeSql #Sql
Once you've printed the #Sql and checked it's ok, unremark the EXEC line and run your script.

error in sql query result

I have this query
DECLARE #Base nvarchar(200)
SET #Base = 'WITH Base AS (SELECT Id, ROW_NUMBER() OVER (ORDER BY Id DESC) RN FROM'
+ Quotename(#SampleWorkTbl) + ')
SELECT * INTO ##temp FROM Base'
EXEC (#Base)
SELECT * FROM ##temp
declare #command nvarchar(max)
Set #command='SELECT TOP 15 [Name],[ImageAddress],(SELECT TOP 1 COUNT(Id) FROM' + QUOTENAME(#SampleWorkTbl) + ') as AllSampleCount FROM ' + QUOTENAME(#SampleWorkTbl) +
' WHERE [Id] IN (SELECT TOP 15 Id From ##temp WHERE RN > ((#Count-1)*15) ORDER BY Id DESC) ORDER BY Id DESC'
exec (#command)
drop table ##temp
I want get [Name],[ImageAddress] and count of Id from any table name that pass to the procedure
but instead of get name , image address and Id I get this data
Id RN
10 1
9 2
8 3
7 4
6 5
5 6
4 7
3 8
2 9
1 10
and when try again i get this error
There is already an object named '##temp' in the database.
#SampleWorkTbl is a name of any table that pass to the this query
how i can fix this problem ?
thank you for you help
Your Query is executing until
EXEC (#Base)
You are getting the
There is already an object named '##temp' in the database.
at
SELECT * FROM ##temp
means you got error somewhere and it didn't reached the point
drop table ##temp
as #Ganesh_Devlekar mentioned
Try adding
if (object_ID('tempdb..##temp')) is not NULL
DROP TABLE ##temp
at the Starting
try this:
For
There is already an object named '##temp' in the database.
Before Creating New Temp Table You need to Use This:
if (object_ID('tempdb..##temp')) is not NULL
DROP TABLE ##temp
You need to add [Name],[ImageAddress],ID these columns to get desire output
SET #Base = 'WITH Base AS (SELECT [Name],[ImageAddress],ID,COUNT(ID) CntID, ROW_NUMBER() OVER (ORDER BY Id DESC) RN FROM'
+ Quotename(#SampleWorkTbl) + ' GROUP BY [Name],[ImageAddress],ID)
SELECT * INTO ##temp FROM Base'