Validation if you're using the correct DB - sql

Is there a way to have a validation script before continuing a script?
So
DECLARE #strServernameToClear as VarChar(100)
DECLARE #strCurrentServer as VarChar(100)
DECLARE #strDatabaseToClear as VarChar (100)
DECLARE #strDatabase as VarChar (100)
SET #strDatabase = (SELECT ##database) << THIS IS WHERE IM HAVING TROUBLE. How to indicate which database it is running against
IF #strCurrentServer <> #strServernameToClear
BEGIN
PRINT '*****************WARNING *****************'
PRINT 'WRONG DB NAME: This server is: ' + #strCurrentServer
PRINT 'If this is the correct server, set #strServernameToClear to ' + #strCurrentServer
RETURN
END
ELSE
EXECUTE ORDER 66

I think this'll work for you:
select #strDatabase = d.name
from sys.sysprocesses p
join sys.databases d on d.database_id = p.dbid
where p.spid = ##SPID

Related

SQL Server SP error Msg 4145, Level 15, State 1

When I try to run individual query for select and/or insert, it works. When I put it in SP and run it for all DB, it errors out.
Msg 4145, Level 15, State 1, Line 45 An expression of non-boolean type
specified in a context where a condition is expected, near 'Addr'.
Declare #command varchar(MAX)
Select #command = '
USE [?]
IF DB_NAME() not like ''%_VER''
BEGIN RETURN END
ElSE
BEGIN
Insert Into [TEST_VER].[dbo].[TestTable]
(ClientName,ID,Type,Filled,FilledDate,Cancelled,CancelledDate,CancellationReason,Deleted,NumberOfPosition,Address,City,State,Country,Annual,AnnualMax,FeePercentage,FeeTotal,GrossProfit,NetProfit,Rate,OTRate,CRate,COTRate,GrossProfit,GrossMargin,ProfitMargin,RegularMarkup,OTMarkup)
select
DB_NAME() as ClientName,
ID,
Type.Description as Type,
Filled,
FilledDate,
Cancelled,
CancelledDate,
CancellationReason.Description as CancellationReason,
Item.Deleted,
NumberOfPosition,
Address.Description as Address,
City.Description as City,
ProvinceState.Description as State,
Country.Description as Country,
PayP.Annual,
PayP.AnnualMaximum,
PayP.FeePercentage,
PayP.FeeTotal,
PayP.GrossProfit,
PayP.NetProfit,
PayT.Rate,
PayT.OTRate,
PayT.CRate,
PayT.COTRate,
PayT.GrossProfit,
PayT.GrossMargin,
PayT.ProfitMargin,
PayT.RegularMarkup,
PayT.OTMarkup
from [Item]
left join [Type] on Item.TypeID = Type.TypeID AND Type.LanguageId = 1
left join [CancellationReason] on Item.CancellationReasonID = CancellationReason.CancellationReasonID AND CancellationReason.LanguageID = 1
left join [Address] on Item.LocationID = Address.AddressID
left join [City] on Address.CityId = City.CityID
left join [ProvinceState] on Address.ProvinceStateId = ProvinceState.ProvinceStateID
left join [Country] on Address.CountryId = Country.CountryID
left join [PayP] on (Item.PaymentID=PayP.ID and Item.TypeID = 1)
left join [PayT] on (Item.PaymentID=PayT.ID and Item.TypeID > 1)
END'
EXEC sp_MSforeachdb #command
The short response is that your sql command is too long.
This undocumented stored procedure sp_msforeachdb doesn't accept a varchar as long as varchar(max). In fact, on SQL SERVER 2019 as seen in the db -fiddle below it only accepts 2000 characters which results in part of your query being cut off. As a result your join expression is incomplete resulting in the error message Msg 4145, Level 15, State 1, Line 45 An expression of non-boolean type specified in a context where a condition is expected, near 'Addr'..
I would recommend a shorter query or creating a stored procedure with your query in a generally accessible db and then running the command from there or rewriting your query to run differently. I've also included a few suggestions at the end of this answer.
You may use the stored procedure as I have used below sp_helptext to find out more about the definition in your db version.
The code and reproducible sample fiddle to prove the above is shown below.
select ##version;
GO
| (No column name) |
| :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Microsoft SQL Server 2019 (RTM-CU6) (KB4563110) - 15.0.4053.23 (X64) <br> Jul 25 2020 11:26:55 <br> Copyright (C) 2019 Microsoft Corporation<br> Express Edition (64-bit) on Windows Server 2019 Standard 10.0 <X64> (Build 17763: ) (Hypervisor)<br> |
exec sp_helptext 'sp_msforeachdb'
GO
| Text |
| :---------------------------------------------------------------------------------------------------------------------------------------------------
/*
* The following table definition will be created by SQLDMO at start of each connection.
* We don't create it here temporarily because we need it in Exec() or upgrade won't work.
*/
create proc sys.sp_MSforeachdb
#command1 nvarchar(2000), #replacechar nchar(1) = N'?', #command2 nvarchar(2000) = null, #command3 nvarchar(2000) = null,
#precommand nvarchar(2000) = null, #postcommand nvarchar(2000) = null
as
set deadlock_priority low
/* This proc returns one or more rows for each accessible db, with each db defaulting to its own result set */
/* #precommand and #postcommand may be used to force a single result set via a temp table. */
/* Preprocessor won't replace within quotes so have to use str(). */
declare #inaccessible nvarchar(12), #invalidlogin nvarchar(12), #dbinaccessible nvarchar(12)
select #inaccessible = ltrim(str(convert(int, 0x03e0), 11))
select #invalidlogin = ltrim(str(convert(int, 0x40000000), 11))
select #dbinaccessible = N'0x80000000' /* SQLDMODbUserProf_InaccessibleDb; the negative number doesn't work in convert() */
if (#precommand is not null)
exec(#precommand)
declare #origdb nvarchar(128)
select #origdb = db_name()
/* If it's a single user db and there's an entry for it in sysprocesses who isn't us, we can't use it. */
/* Create the select */
exec(N'declare hCForEachDatabase cursor global for select name from master.dbo.sysdatabases d ' +
N' where (d.status & ' + #inaccessible + N' = 0)' +
N' and (DATABASEPROPERTYEX(d.name, ''UserAccess'') <> ''SINGLE_USER'' and (has_dbaccess(d.name) = 1))' )
declare #retval int
select #retval = ##error
if (#retval = 0)
exec #retval = sys.sp_MSforeach_worker #command1, #replacechar, #command2, #command3, 1
if (#retval = 0 and #postcommand is not null)
exec(#postcommand)
declare #tempdb nvarchar(258)
SELECT #tempdb = REPLACE(#origdb, N']', N']]')
exec (N'use ' + N'[' + #tempdb + N']')
return #retval
Here I run the query with the 2000 max and you will see that part of the query is cut off
Declare #command varchar(2000)
Select #command = '
USE [?]
IF DB_NAME() not like ''%_VER''
BEGIN RETURN END
ElSE
BEGIN
Insert Into [TEST_VER].[dbo].[TestTable]
(ClientName,ID,Type,Filled,FilledDate,Cancelled,CancelledDate,CancellationReason,Deleted,NumberOfPosition,Address,City,State,Country,Annual,AnnualMax,FeePercentage,FeeTotal,GrossProfit,NetProfit,Rate,OTRate,CRate,COTRate,GrossProfit,GrossMargin,ProfitMargin,RegularMarkup,OTMarkup)
select
DB_NAME() as ClientName,
ID,
Type.Description as Type,
Filled,
FilledDate,
Cancelled,
CancelledDate,
CancellationReason.Description as CancellationReason,
Item.Deleted,
NumberOfPosition,
Address.Description as Address,
City.Description as City,
ProvinceState.Description as State,
Country.Description as Country,
PayP.Annual,
PayP.AnnualMaximum,
PayP.FeePercentage,
PayP.FeeTotal,
PayP.GrossProfit,
PayP.NetProfit,
PayT.Rate,
PayT.OTRate,
PayT.CRate,
PayT.COTRate,
PayT.GrossProfit,
PayT.GrossMargin,
PayT.ProfitMargin,
PayT.RegularMarkup,
PayT.OTMarkup
from [Item]
left join [Type] on Item.TypeID = Type.TypeID AND Type.LanguageId = 1
left join [CancellationReason] on Item.CancellationReasonID = CancellationReason.CancellationReasonID AND CancellationReason.LanguageID = 1
left join [Address] on Item.LocationID = Address.AddressID
left join [City] on Address.CityId = City.CityID
left join [ProvinceState] on Address.ProvinceStateId = ProvinceState.ProvinceStateID
left join [Country] on Address.CountryId = Country.CountryID
left join [PayP] on (Item.PaymentID=PayP.ID and Item.TypeID = 1)
left join [PayT] on (Item.PaymentID=PayT.ID and Item.TypeID > 1)
END'
select 1
select #command
GO
| (No column name) |
| ---------------: |
| 1 |
USE [?]
IF DB_NAME() not like '%_VER'
BEGIN RETURN END
ElSE
BEGIN
Insert Into [TEST_VER].[dbo].[TestTable]
(ClientName,ID,Type,Filled,FilledDate,Cancelled,CancelledDate,CancellationReason,Deleted,NumberOfPosition,Address,City,State,Country,Annual,AnnualMax,FeePercentage,FeeTotal,GrossProfit,NetProfit,Rate,OTRate,CRate,COTRate,GrossProfit,GrossMargin,ProfitMargin,RegularMarkup,OTMarkup)
select
DB_NAME() as ClientName,
ID,
Type.Description as Type,
Filled,
FilledDate,
Cancelled,
CancelledDate,
CancellationReason.Description as CancellationReason,
Item.Deleted,
NumberOfPosition,
Address.Description as Address,
City.Description as City,
ProvinceState.Description as State,
Country.Description as Country,
PayP.Annual,
PayP.AnnualMaximum,
PayP.FeePercentage,
PayP.FeeTotal,
PayP.GrossProfit,
PayP.NetProfit,
PayT.Rate,
PayT.OTRate,
PayT.CRate,
PayT.COTRate,
PayT.GrossProfit,
PayT.GrossMargin,
PayT.ProfitMargin,
PayT.RegularMarkup,
PayT.OTMarkup
from [Item]
left join [Type] on Item.TypeID = Type.TypeID AND Type.LanguageId = 1
left join [CancellationReason] on Item.CancellationReasonID = CancellationReason.CancellationReasonID AND CancellationReason.LanguageID = 1
left join [Address] on Item.LocationID = Address.AddressID
left join [City] on Address.CityId = City.CityID
left join [ProvinceState] on Address.ProvinceStateId = P
db<>fiddle here
#Larnu has also made some suggestions about alternatives such as option 1 and option 2 which you may consider in your own time.

Strange exec and sp_executesql different behavior

I have a small stored procedure (SQl Server 2012).
IF I run it using:
exec spSelRegion #bOver21 = 1
I Get different results than if I run it using:
exec sp_executesql N'spSelRegion',N'#bOver21 bit',#bOver21=1
What is the difference?
ALTER PROCEDURE [dbo].[spSelRegion]
(
#ID int = NULL
,#Name varchar(128) = NULL
,#OrderBy varchar(16) = 'ID'
,#bOver21 bit = null
)
AS
SELECT distinct
r.[ID],
r.[Name],
r.[dInserted],
r.[sInserted],
r.[dUpdated],
r.[sUpdated],
r.[timestamp]
FROM
[dbo].[tblRegion] r
left outer join tblCountyRegion cr
on r.ID = cr.RegionNbr
WHERE
(r.[ID] = #ID or #ID is null)
AND (r.[Name] = #Name or #Name is null)
AND (#bOver21 is null and r.[ID] >20
OR (#bOver21 = 1 and r.[ID] > 20 and cr.IsActive=1)
OR (#bOver21 = 0 and r.[ID] >= 21 and r.id < 31))
I don't want to make this more complecated than it is . But after a microsoft update today , some stored procedures are now runnig using sp_executesql instead of Exec and this is source of the issue.
You would need to run your dynamic SQL with the parameter specified. Without that, it assumes a null value passed. So this:
exec sp_executesql N'spSelRegion #bOver21 = #bOver21',N'#bOver21 bit',#bOver21=1

How can I replace a cursor in sql server for printing an output

I want to know how to replace a cursor in SQL Server because it performs badly. I tried using a CTE for list recursively but I don't know how to output the columns. I want to print it because I want paste the output in a .txt file.
This is the CTE so far:
WITH EmpleadosRec (EmpNombre,EmpID)
AS
(
SELECT[First Name],ID from employees where id=1
UNION ALL
select e.[First Name], ID+1 from employees as e
INNER JOIN EmpleadosRec er
ON e.id = er.EmpID
WHERE e.id < 5
)
select *
from EmpleadosRec
DECLARE #id int = 1
DECLARE #FirstName varchar(50)
WHILE #id < 5
BEGIN
SELECT #FirstName = [First Name] from employees where id = #id
Print '#FirstName = ' + #FirstName + ' #id = ' + CAST(#id as varchar(50))
SET #id = #id + 1
END
GO
But this method is bad if you process a large number of rows.
In this case check MSDN bcp Utility
bcp "SELECT FirstName, LastName FROM AdventureWorks2012.Person.Person ORDER BY LastName, Firstname" queryout Contacts.txt -c -T
Also in SQL Management Studio
Menu Query -> Results To -> Results To File

SQL Server FileStream - How to acquire files path

I'm working on this application where I need to upload large data files to my SQL Server DB, and I've been using FileStream to do it more efficiently.
I understand the files are stored directly into my system's folders (C:\CryptoDB).
The thing is, I need to manipulate these files (decrypt them) but I haven't been able to recover their filepath.
Doing so, I would be able to manipulate them directly, not having to re-download them via SQL, which is a real waste.
What I've been able to do so far:
My table:
CREATE TABLE [arquivo] (
[idUsuario] INT NOT NULL,
[fileState] INT NOT NULL,
[fileContent] varbinary(max) FILESTREAM,
[fileName] VARCHAR (150) NULL,
[fileSize] VARCHAR (50) NULL,
id UNIQUEIDENTIFIER ROWGUIDCOL NOT NULL UNIQUE,
CONSTRAINT [FK_arquivo_usuario] FOREIGN KEY ([idUsuario]) REFERENCES usuario(id)
);
Insert:
Insert into arquivo(id, idUsuario, fileState, fileContent, fileName, fileSize) Values(
newId(),
1,
5,
(SELECT * FROM OPENROWSET(BULK 'c:\medio.jpeg', SINGLE_BLOB) AS varbinary(max)) ,
'medio.jpeg',
'123'
)
And when I try to recover the filepath:
DECLARE #filePath varchar(max)
SELECT #filePath = fileContent.PathName()
FROM arquivo
PRINT #filepath
The result I get:
\\TEHORT-PC\MSSQLSERVER\v02-A60EC2F8-2B24-11DF-9CC3-AF2E56D89593\CryptoDB\dbo\arquivo\fileContent\31E3697E-0576-4B0F-B0AA-6E046F4116A1\VolumeHint-HarddiskVolume2
Where the file actually is:
C:\CryptoDB\DATA\902a7d8d-c8c1-43b0-8c94-b12319293f42\7febdbd1-02c6-4b00-aa3c-a72bee80ef9c\
SQL query for get physical location of all FILESTREAM data (source)
SELECT t.name AS 'table',
c.name AS 'column',
fg.name AS 'filegroup_name',
dbf.type_desc AS 'type_description',
dbf.physical_name AS 'physical_location'
FROM sys.filegroups fg
INNER JOIN sys.database_files dbf
ON fg.data_space_id = dbf.data_space_id
INNER JOIN sys.tables t
ON fg.data_space_id = t.filestream_data_space_id
INNER JOIN sys.columns c
ON t.object_id = c.object_id
AND c.is_filestream = 1
All FILESTREAM BLOB-fields query result sample
SQL query for get subfolders for FILESTREAM data on server:
(These tables only used within dedicated Administrator connection (DAC)).
SELECT o.name AS [Table], cp.name AS [Column], r.rsguid AS [Rowset GUID], rs.colguid AS [Column GUID] FROM SYS.SYSROWSETS r CROSS APPLY sys.sysrscols rs
JOIN sys.partitions p ON rs.rsid = p.partition_id
JOIN sys.objects o ON o.object_id = p.object_id
JOIN sys.syscolpars cp ON cp.colid = rs.rscolid
WHERE rs.colguid IS NOT NULL AND o.object_id = cp.id AND r.rsguid IS NOT NULL AND r.rowsetid = rs.rsid AND o.name = 'DOCUMENT' and cp.name = 'DIGITAL_FILE';
2.1. Query result:
Table: DOCUMENT
Column: DIGITAL_FILE
Rowset GUID: 0x6AA5E6045794D34D8B1FAC0F49A49B0A
Column GUID: 0xD756E638FB2CC843AE98F489B57F6D7D
Calculating Sub-Path from this guids:
0x6AA5E6045794D34D8B1FAC0F49A49B0A equals this path:
04e6a56a-9457-4dd3-8b1f-ac0f49a49b0a
[reversed 6AA5E604]-[reversed 5794]-[reversed D34D]-[reversed 8B1F]-[original AC0F49A49B0A]
0xD756E638FB2CC843AE98F489B57F6D7D equals this path:
38e656d7-2cfb-43c8-ae98-f489b57f6d7d (rules in previus guid parsing)
2.2 Result calculated full path for FILESTREAM storage:
i:\SQL Base posc_astrachan FileStreams\GTMK\GTM_FILE_STREAM\04e6a56a-9457-4dd3-8b1f-ac0f49a49b0a\38e656d7-2cfb-43c8-ae98-f489b57f6d7d
Get original filename for BLOB-value in NTFS-folder.
3.1. Stored procedure for query advanced SQL Server Page info
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[procDBCC_PAGE]
#db_name varchar (500),
#filenum INT,
#pagenum INT
AS
BEGIN
SET NOCOUNT ON
DBCC TRACEON (3604);
DBCC PAGE (#db_name, #filenum, #pagenum, 3) WITH TABLERESULTS;
SET NOCOUNT OFF
END
3.2. Stored procedure for query original filename for FILESTREAM'ed BLOB-field of table
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[procFindLogSequenceNumber]
-- #TableName varchar (500),
#instanceS varchar (19), -- key value for filed INSTANCE_S
#tableName varchar(500), -- DOCUMENT
#keyFieldName varchar(500), -- INSTANCE_S
#LogSequenceNumber varchar (500) OUTPUT
AS
SET NOCOUNT ON
DECLARE #db_name varchar (500)
DECLARE #filenum INT
DECLARE #pagenum INT
DECLARE #slotnum INT
DECLARE #rid varchar (100)
DECLARE #ridDotted varchar (100)
DECLARE #parent_object varchar (500)
DECLARE #sql nvarchar(2000)
DECLARE #sqlTable Table(physloc varchar(100))
DECLARE #DBCC_PAGE_Output Table ([ParentObject] varchar (MAX), [Object] varchar (MAX), [Field] varchar (MAX), [VALUE] varchar (MAX))
SET #db_name = db_name()
SET #sql = 'SELECT top 1 sys.fn_PhysLocFormatter (%%physloc%%) AS [PhysicalRID] FROM '+#tableName+' WHERE '
+#keyFieldName+' = '''+#instanceS+''''
INSERT #sqlTable (physloc)
EXECUTE sp_executesql #sql
SET #rid = (select top 1 physloc from #sqlTable)
if #rid is NULL
BEGIN
RETURN -1;
END
-- parse (#rid): (1:1172779:6) 1-#filenum, 2- #pagenum, 3- #slotnum
SET #ridDotted = Replace(#rid, ':', '.');
SET #ridDotted = Replace(#ridDotted, '(', '');
SET #ridDotted = Replace(#ridDotted, ')', '');
SET #filenum = (SELECT Parsename(#ridDotted, 3))
SET #pagenum = (SELECT Parsename(#ridDotted, 2))
SET #slotnum = (SELECT Parsename(#ridDotted, 1))
INSERT #DBCC_PAGE_Output ([ParentObject], [Object], [Field], [VALUE])
EXECUTE procDBCC_PAGE #db_name, #filenum , #pagenum
SET #parent_object = (SELECT TOP 1 [ParentObject] FROM #DBCC_PAGE_Output WHERE [Field] = 'INSTANCE_S'
AND [VALUE] = #instanceS)
--CreateLSN field Only
SET #LogSequenceNumber = (SELECT [VALUE] FROM #DBCC_PAGE_Output WHERE
[ParentObject] = #parent_object AND
[Field] = 'CreateLSN'
)
if #LogSequenceNumber is NULL
BEGIN
RETURN -1;
END
-- result 0006c050:00000120:0090 (442448:288:144)
-- clear (...)
SET #LogSequenceNumber = Replace(#LogSequenceNumber, ' ', '.');
SET #LogSequenceNumber = (SELECT Parsename(#LogSequenceNumber, 2))
--replace ":" to "-"
SET #LogSequenceNumber = Replace(#LogSequenceNumber, ':', '-');
SET NOCOUNT OFF
3.3. Sample query for stored procedure for get filename on NTFS folder for BLOB:
declare #filestreamFileName varchar(500);
exec procFindLogSequenceNumber 'ZW_NU9hGZ0CKoSXYAoc', 'DOCUMENT', 'INSTANCE_S', #filestreamFileName OUTPUT
select #filestreamFileName
3.4. Result (original file name in NTFS folder):
0003137a-00001244-00d0
3.5. Result full path:
i:\SQL Base posc_astrachan FileStreams\GTMK\GTM_FILE_STREAM\04e6a56a-9457-4dd3-8b1f-ac0f49a49b0a\38e656d7-2cfb-43c8-ae98-f489b57f6d7d\0003137a-00001244-00d0
The path you get is correct, you are supposed to get the network share path not the local path and use SqlFileStream to open a stream.
https://msdn.microsoft.com/en-us/library/system.data.sqltypes.sqlfilestream%28v=vs.110%29.aspx
You could also get a file handle using OpenSqlFilestream method, i.e. to use it in Windows API.
https://msdn.microsoft.com/en-us/library/bb933972.aspx
Alexander's answer is great, saved me a LOT of trouble correlating page/slot numbers to actual LSNs. In my case using SQL Server 2008 R2 I had to make some adjustments to his SP to get it working, those were:
The SPs first parameter:
#instanceS varchar (100), -- key value for filed INSTANCE_S
In my case this is a uniqueidentifier so I needed a bigger varchar, original value was 19.
When querying DBCC PAGE Output:
SET #parent_object = (SELECT TOP 1 [ParentObject] FROM
#DBCC_PAGE_Output WHERE [Field] = #keyFieldName AND [VALUE] =
#instanceS)
It originaly stated "[Field] = 'INSTANCE_S'" which apparently hardcoded a value that worked for OP but not for me. It needed to match the name of the FILESTREAM table's key field.
Also to clarify the SPs input params a bit:
#instanceS = The actual column value which identifies the row. Will
this always match the column set as the table's "RowGuid"?
#tableName = Pretty clear. The FILESTREAM table's name.
#keyFieldName = The name of the table's key column. Should be the
source column from where #instanceS was taken.

TSQL: Using a Table in a Variable in a Function

I'm trying to do a select from a table that will need to be in a variable. I'm working with tables that are dynamically created from an application. The table will be named CMDB_CI_XXX, where XXX will be an integer value based on a value in another table. The ultimate goal is to get the CI Name from the table.
I've tried passing the pieces that make up the table name to a function and string them together and then return the name value, but I'm not allowed to use an EXEC statement in a function.
This is what I want to execute to get the name value back:
Select [Name] from 'CMDB_CI_' + C.CI_TYPE_ID + Where CI_ID = c.CI_ID
This is the code in the SP that I'd like to use the function in to get the name value:
SELECT
CI_ID,
C.CI_TYPE_ID,
CI_CUSTOM_ID,
STATUS,
CI_TYPE_NAME,
--(Select [Name] from CMDB_CI_ + C.CI_TYPE_ID + Where CI_ID = c.CI_ID)
FROM [footprints].[dbo].[CMDB50_CI_COMMON] c
join [footprints].[dbo].[CMDB50_CI_TYPE] t
on c.CI_TYPE_ID = t.CI_TYPE_ID
where status <> 'retired'
order by CI_TYPE_NAME
I'm not sure what to do with this. Please help?
Thanks,
Jennifer
-- This part would be a SP parameter I expect
DECLARE #tableName varchar(100)
SET #tableName = 'CMDB_CI_508'
-- Main SP code
DECLARE #sqlStm VARCHAR(MAX)
SET #sqlStm = 'SELECT *
FROM '+ #tableName
EXEC (#sqlStm)
Fiddle http://sqlfiddle.com/#!3/436a7/7
First off, yes, I know it's a bad design. I didn't design it. It came with the problem tracking software that my company bought for our call center. So I gave up altogether on the approach I was going for and used a cursor to pull all the the names from the various tables into one temp table and then used said temp table to join to the original query.
ALTER Proc [dbo].[CI_CurrentItems]
As
Declare #CIType nvarchar(6)
Declare #Qry nvarchar(100)
/*
Create Table Temp_CI
( T_CI_ID int,
T_CI_Type_ID int,
T_Name nvarchar(400)
)
*/
Truncate Table Temp_CI
Declare CI_Cursor Cursor For
select distinct CI_TYPE_ID FROM [footprints].[dbo].[CMDB50_CI_COMMON]
where STATUS <> 'Retired'
Open CI_Cursor
Fetch Next from CI_Cursor into #CIType
While ##FETCH_STATUS = 0
BEGIN
Set #Qry = 'Select CI_ID, CI_Type_ID, Name from Footprints.dbo.CMDB50_CI_' + #CIType
Insert into Temp_CI Exec (#Qry)
Fetch Next from CI_Cursor into #CIType
END
Close CI_Cursor
Deallocate CI_Cursor
SELECT CI_ID,
C.CI_TYPE_ID,
CI_CUSTOM_ID,
STATUS,
CI_TYPE_NAME,
T_Name
FROM [footprints].[dbo].[CMDB50_CI_COMMON] c
JOIN [footprints].[dbo].[CMDB50_CI_TYPE] t
ON c.CI_TYPE_ID = t.CI_TYPE_ID
JOIN Temp_CI tc
ON c.CI_ID = tc.T_CI_ID
AND t.CI_TYPE_ID = tc.T_CI_TYPE_ID
WHERE STATUS <> 'retired'
ORDER BY CI_TYPE_NAME