I am running SQL Job (SQL Server 20208 R2) and I want the results of the script to save to a folder as pipe delimited. Is there any way of doing that by adding to the script? Below is the script. If not can I do it any other way?
SELECT Distinct
(SELECT REPLACE(CONVERT(VARCHAR(10),PatientDemographics.DateofBirth,101),'/','')) as DOB
, (SELECT REPLACE(CONVERT(VARCHAR(10),ScheduleEntry.ScheduleDate,101),'/','')) as DateofService
, RTRIM(LTRIM(Insurances.EligibilityPayorNumber)) as InsurancePayorCode
, RTRIM(LTRIM(ContractFacilityProviders.NPI)) as ProviderID
, RTRIM(LTRIM(PatientInsuranceProfiles.Insurance1PolicyNumber)) as SubscriberInsuranceID
, RTRIM(LTRIM(PatientInsuranceProfiles.Insurance1PolicyGroupNumber)) as SubscriberGroupNumber
, RTRIM(LTRIM(PatientDemographics.firstname)) as SubscriberFirstName
, RTRIM(LTRIM(PatientDemographics.MiddleInitial)) as SubscriberMiddleInitial
, RTRIM(LTRIM(PatientDemographics.Lastname)) as SubscriberLastName
FROM
ScheduleEntry
LEFT JOIN
PatientDemographics ON ScheduleEntry.PatientAccount = PatientDemographics.AccountNumber
LEFT JOIN
Providers ON ScheduleEntry.ResourceCode = Providers.MedStarProviderIdentifier
LEFT JOIN
Facilities ON ScheduleEntry.FacilityCode = Facilities.MedStarFacilityIdentifier
LEFT JOIN
AddedResource ON ScheduleEntry.ResourceCode = AddedResource.AddedResourceCode
LEFT JOIN
Caregiver ON ScheduleEntry.ResourceCode = Caregiver.CaregiverCode
LEFT JOIN
PatientInsuranceProfiles ON ScheduleEntry.PatientAccount = PatientInsuranceProfiles.PatientAccountNumber
LEFT JOIN
Insurances ON PatientInsuranceProfiles.Insurance1Mnemonic = Insurances.Mnemonic
LEFT JOIN
ContractFacilityProviders ON PatientDemographics.PrimaryPhysician = ContractFacilityProviders.ProviderIdentifier
WHERE
ScheduleEntry.ScheduleDate >= getdate()
AND ScheduleEntry.ScheduleDate <= getDate() + .50
AND PatientInsuranceProfiles.Insurance1ContractIdentifier = ContractFacilityProviders.ContractIdentifier
AND PatientinsuranceProfiles.ActiveFlag = 1
AND EligibilityPayorNumber > 1
AND ContractFacilityProviders.NPI > 1
ORDER BY
SubscriberLastName
You can xp_cmdshell with something like....
SELECT DISTINCT
--your columns
INTO ##PIPE_FILE
FROM YourTables
INNER JOIN YourOtherTables
EXECUTE master.dbo.xp_cmdshell
'bcp "SELECT * FROM ##PIPE_FILE " queryout C:\Folder\Pipes.txt -t"|" -c -T '
Several ideas
1) Write an SSIS package to export to a flat file, using the pipe as the delimiter.
2) Use BCP as stated already
3) Use sqlcmd to output the result
SSIS will be a nice solution for a SQL job.
I would also echo the previous posters who suggested checking that your aren't negating the effects of your left joins by using the tables in the where clause
EDIT: If you don't have access to xp_cmdshell (many DBAs turn this
off)
The following will take the results of #TempPipe and dynamically save it as a pipe delimited (with a header -- optional) to your desired location.
Now, you will need the stored procedure listed below, along with the appropriate writes.
-- Assumes your query will be saved to #TempPipe
Select * Into #TempPipe from OD
-- Set Destination File
Declare #Destination varchar(250) = 'C:\Working\Test_Pipe.txt'
-- Construct Field Name and Header from #TempPipe
Declare #Header varchar(max) = '>>>'
Select #Header = #Header +']|['+Name from (select * from tempdb.sys.columns where object_id = object_id('tempdb..#TempPipe') ) A Order by column_id
Select #Header = Replace(#Header,'>>>]|','')+']'
Declare #SelectHead varchar(max) = 'Select Pipe=cast(Replace(Replace('''+#Header+''',''['',''''),'']'','''') as varchar(max)) '
Declare #SelectData varchar(max) = 'Select Pipe=cast(concat('+Replace(#Header,'|',',''|'',')+') as varchar(max)) from #TempPipe '
--If Version<2012 Declare #SelectData varchar(max) = 'Select Pipe=cast(cast('+Replace(#Header,'|',' as varchar(500))+''|''+cast(')+' as varchar(500)) as varchar(max)) from #TempPipe '
Declare #SQL varchar(max) ='
Declare #String varchar(max) = '''';
Select #String = #String + Pipe + char(13)+char(10) From ('+#SelectHead+' Union All '+#SelectData+' ) A
Exec [dbo].[prc-Write-To-File] #String, ''' + #Destination +'''
'
--Select #SQL
Exec(#SQL)
The stored procedure to write any string to any file
EXEC sp_configure 'show advanced options', 1
GO
EXEC sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO
CREATE Procedure [dbo].[prc-Write-To-File] (#text as Varchar(Max), #Filename Varchar(200)) AS
Begin
Declare #Object int,#rc int,#FileID Int
EXEC #rc = sp_OACreate 'Scripting.FileSystemObject', #Object OUT
EXEC #rc = sp_OAMethod #Object , 'OpenTextFile' , #FileID OUT , #Filename , 2 , 1
Set #text = Replace(Replace(Replace(#text,'&','&'),'<' ,'<'),'>','>')
EXEC #rc = sp_OAMethod #FileID , 'WriteLine' , Null , #text
Exec #rc = [YourDatabaseName].dbo.sp_OADestroy #FileID
Declare #Append bit
Select #Append = 0
If #rc <> 0
Begin
Exec #rc = [YourDatabaseName].dbo.sp_OAMethod #Object, 'SaveFile',null,#text ,#Filename,#Append
End
Exec #rc = [YourDatabaseName].dbo.sp_OADestroy #Object
End
Small sample of the text file generated
ODNr|ODID|ODClass|ODTitle|ODLMUsr|ODLMUTC|ODDeleted
0|UNDEF|UNDEF|Undefined|2|Apr 5 2016 1:40PM|0
1|SYSTEM|UNDEF|System|2|Apr 5 2016 1:40PM|0
2|UNDEF|USER|Cappelletti, John|2|Apr 12 2016 7:04PM|0
3|UNDEF|UNDEF|Daily Production Summary|2|Apr 14 2016 12:28PM|0
Related
I have two procedure, one just return image in varbinary format and another one get that value and assign it in a variable. But I am getting:
String or binary data would be truncated.
Here I included both procedure below:
ALTER PROCEDURE [dbo].[Common_Sp_GetImage](#imagePath varchar(MAX), #Result VARBINARY(max) OUTPUT)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
--EXEC master..xp_cmdshell 'net use Y: \\192.168.1.175\Rack /user:192.168.1.175\SPLITPC07 IT#2022';
-- Insert statements for procedure here
DECLARE #SQL varchar(max) =
N'SELECT #Result = BulkColumn
FROM OPENROWSET(BULK ''Y:' + #imagePath + N''', SINGLE_BLOB) AS t';
EXECUTE sp_executesql #SQL, N'#Result varbinary(max) OUTPUT', #Result OUTPUT;
RETURN #Result;
END
Another one is:
ALTER PROCEDURE [dbo].[Sales_Sp_MoneyRecipt]
-- Add the parameters for the stored procedure here
#CollectionId int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Your insert TSQL here.
declare #CompanyImage varbinary(max)
declare #ProjectShornaliImage varbinary(max)
declare #ProjectSunvalleyImage varbinary(max)
EXEC GetImageProcedure '\Common\SwadeshLogo.jpg', #CompanyImage OUTPUT;
EXEC GetImageProcedure '\Common\ShornaliLogoEn.jpg', #ProjectShornaliImage OUTPUT;
EXEC GetImageProcedure '\Common\SunvalleyLogoEn.jpg', #ProjectSunvalleyImage OUTPUT;
select
'Money Receipt' ReportName,
dbo.GetCompanyName() as CompanyName,
dbo.GetCompanyAddress() as CompanyAddress,
ci.MRIdentity,
ci.MRNo,
ci.MRDate,
si.ApplicationId,
c.ClientName,
dbo.GetSalesMasterName(si.PlotType, 4) PlotType,
cti.CollectionTypeName CollectionType,
CONCAT(Left(ci.InstallmentFrom, 4), + '-' + DateName( month , DateAdd( month , CONVERT(int, RIGHT(ci.InstallmentFrom, 2)) , -1 ))) FromYearMonth,
CONCAT(Left(ci.InstallmentTo, 4), + '-' + DateName( month , DateAdd( month , CONVERT(int, RIGHT(ci.InstallmentTo, 2)) , -1 ))) ToYearMonth,
si.ProjectId,
Case when si.ProjectId = 1 then #ProjectShornaliImage else #ProjectSunvalleyImage end as ProjectImage,
dbo.GetProjectNameEnglish(si.ProjectId) ProjectName,
si.TotalArea,
dbo.GetMasterName(ci.MRType, 49) MRType,
ci.ChequeNo,
ci.ChequeDate,
b.BankName,
ci.Amount,
#CompanyImage as CompanyImage
from Sales_CollectionInfo ci
inner join Sales_CollectionTypeInfo cti on ci.CollectionType = cti.CollectionTypeId
inner join Sales_SaleInfo si on ci.SalesId = si.SaleId
inner join Sales_ClientInfo c on si.ClientId = c.ClientId
left join BankInfo b on ci.ChequeBank = b.Id
where ci.CollectionId = #CollectionId
END
I have been trying my darndest to get the code described below to work. I am very inexpert at MSSMS and SQL. That said, I love the efficiency of SQL databases and would really love to make this code work.
I have tested my CSV files with this code:
BULK INSERT BCPData
FROM 'D:\cheese\bcp_test.csv'
WITH (FIRSTROW = 2,
FIELDTERMINATOR = ','
,ROWTERMINATOR = '0x0a'
);
GO
They import easily and the data appears.
However, if I try to use the code shown below (I need an code that automatically imports multiple CSV files into my table) I only get "NULL" results in the columns.
My query is as follows:
exec ImportFiles 'd:\cheese\' , 'd:\cheese\Archive' , 'bcp*.csv' , 'MergeBCPData'
I run this query after using the following code to create the necessary stored procedures:
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[ImportFiles]') and `OBJECTPROPERTY(id, N'IsProcedure') = 1)`
drop procedure [dbo].[ImportFiles]
GO
create procedure ImportFiles
#FilePath varchar(1000) = 'd:\cheese\' ,
#ArchivePath varchar(1000) = 'd:\cheese\Archive\' ,
#FileNameMask varchar(1000) = 'bcp*.csv' ,
#MergeProc varchar(128) = 'MergeBCPData'
AS
set nocount on
declare #ImportDate datetime
select #ImportDate = getdate()
declare #FileName varchar(1000) ,
#File varchar(1000)
declare #cmd varchar(2000)
create table ##Import (s varchar(8000))
create table #Dir (s varchar(8000))
/*****************************************************************/
-- Import file
/*****************************************************************/
select #cmd = 'dir /B ' + #FilePath + #FileNameMask
delete #Dir
insert #Dir exec master..xp_cmdshell #cmd
delete #Dir where s is null or s like '%not found%'
while exists (select * from #Dir)
begin
select #FileName = min(s) from #Dir
select #File = #FilePath + #FileName
select #cmd = 'bulk insert'
select #cmd = #cmd + ' ##Import'
select #cmd = #cmd + ' from'
select #cmd = #cmd + ' ''' + replace(#File,'"','') + ''''
select #cmd = #cmd + ' with (FIELDTERMINATOR = '','''
select #cmd = #cmd + ',ROWTERMINATOR = ''0x0a''
)'
truncate table ##Import
-- import the data
exec (#cmd)
-- remove filename just imported
delete #Dir where s = #FileName
exec #MergeProc
-- Archive the file
select #cmd = 'move ' + #FilePath + #FileName + ' ' + #ArchivePath + #FileName
exec master..xp_cmdshell #cmd
end
drop table ##Import
drop table #Dir
go
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[MergeBCPData]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[MergeBCPData]
GO
create procedure MergeBCPData
AS
set nocount on
-- insert data to production table
insert BCPData
(
City ,
Visit_Duration_Seconds ,
Timezone ,
Most_Likely_Company
)
select
SUBSTRING('City', 1, 5),
SUBSTRING('Visit_Duration_Seconds', 1, 12),
SUBSTRING('Timezone', 1, 3),
SUBSTRING('Most_Likely_Company',1, 30)
from ##Import
go
Any help would be very appreciated. I'm hopeful it is just an error that my inexperienced eyes are too novel to catch. THANK YOU!
You stated 'I need an code that automatically imports multiple CSV files into my table'. Is there a pattern in the file names that you can exploit? Do the file names have dates in them, per chance? If there is some repeating pattern that you can exploit, like a series of dates, you can loop through all the files in your folder, and append all files to one table, in one go. Check out the code below, and post back if you have questions.
DECLARE #intFlag INT
SET #intFlag = 1
WHILE (#intFlag <=50) – we are running 50 loops...change this as needed
BEGIN
PRINT #intFlag
declare #fullpath1 varchar(1000)
select #fullpath1 = '''\\your_path_here\FTP\' + convert(varchar, getdate()- #intFlag , 112) + '_Daily.csv'''
declare #cmd1 nvarchar(1000)
select #cmd1 = 'bulk insert [dbo].[Daily] from ' + #fullpath1 + ' with (FIELDTERMINATOR = ''\t'', FIRSTROW = 5, ROWTERMINATOR=''0x0a'')'
exec (#cmd1)
SET #intFlag = #intFlag + 1
END
Here are some common date formats.
http://www.sql-server-helper.com/tips/date-formats.aspx
Again, I'm assuming you have dates in your file names.
In Sql Server
I have sample script
Declare #V table (name varchar(100))
INSERT INTO #V(name)
select name from sys.databases where database_id > 6
select NAME from #V
If I execute this Script I get the user databases list
In my instance I have below Databases :
DatabaseName
mohan
Ravi
How can I dynamically append the Database names to below script and execute the script in below Databases
Declare #V table (ID INT,name varchar(100))
INSERT INTO #V(Id,name)
select ROW_NUMBER()OVER(ORDER BY NAME),name from sys.databases where database_id > 6
DECLARE #LoopCounter INT , #MaxId INT,
#Name NVARCHAR(100)
SELECT #LoopCounter = min(id) , #MaxId = max(Id)
FROM #V
WHILE(#LoopCounter IS NOT NULL
AND #LoopCounter <= #MaxId)
BEGIN
SELECT #Name = Name
FROM #V WHERE Id = #LoopCounter
PRINT #Name
SET #LoopCounter = #LoopCounter + 1
END
DECLARE #DatabaseName VARCHAR(50) = #Name
, #SQL NVARCHAR(MAX);
SET #SQL = N'USE ' + QUOTENAME(#DatabaseName)
+'CREATE TABLE T(ID INT)';
--PRINT(#SQL);
EXECUTE(#SQL);
So in all user databases Table will be created . I have tried with sp_msforeachdb
script :
DECLARE #Sql AS VARCHAR(4000)
SET #Sql = 'IF ''?'' NOT IN (''master'',''tempdb'',''model'',''msdb'',''ReportServer'',''ReportServerTempDB'')
EXECUTE ('' USE [?] CREATE TABLE T (ID INT)'')'
EXEC sp_MSforeachdb #command1 = #Sql
But I'm looking for looping script .How to append those names to the Script
No need for a loop here. You can generate the entire statement in one pass. This query populates a var that contains multiple USE and CREATE TABLE statements:
DECLARE #Qry NVARCHAR(MAX) = '';
-- Build dynamic SQL statement here.
-- 1 Row returned per target database .
SELECT
#Qry +=
'
USE' + QUOTENAME(Name) + ';
CREATE TABLE T
(
ID INT
)
;
'
FROM
sys.Databases
WHERE
database_id > 6
;
-- Remove comments from last line when happy with query.
PRINT #Qry
--EXECUTE sp_ExecuteSQL #Qry
Returns
USE [X];
CREATE TABLE T
(
ID INT
)
;
USE [Y];
CREATE TABLE T
(
ID INT
)
;
...
I want to sum up values from several databases. At this moment I have three databases: SPA_PROD, SPB_PROD and SPC_PROD.
My SQL query:
IF EXISTS (SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(N'[dbo].[TESTSUM]')
AND TYPE IN (N'P',N'PC'))
DROP PROCEDURE [dbo].[TESTSUM]
GO
CREATE PROC TESTSUM
AS
BEGIN
DECLARE #dbName SYSNAME,
#ObjectSUM INT,
#d datetime
SET #d = '20141113'
DECLARE #SQL NVARCHAR(MAX)
DECLARE #DBObjectStats TABLE (
--DBName SYSNAME,
DBObjects INT)
DECLARE curAllDBs CURSOR FOR
SELECT name
FROM MASTER.dbo.sysdatabases
WHERE name like '%PROD'
ORDER BY name
OPEN curAllDBs
FETCH curAllDBs INTO #dbName
WHILE (##FETCH_STATUS = 0) -- db loop
BEGIN
--SQL QUERY
SET #SQL = 'select #dbObjects = sum(doctotal) from ' +
QuoteName(#dbName) + '..Invoice
where DocDate = ''' + cast(#d as varchar(25)) + ''''
PRINT #SQL -- Debugging
EXEC sp_executesql #SQL, N'#dbObjects int output',
#dbObjects = #ObjectSUM output
INSERT #DBObjectStats
SELECT #ObjecSUM
FETCH curAllDBs INTO #dbName
END
CLOSE curAllDBs
DEALLOCATE curAllDBs
-- Return results
SELECT sum(DBObjects) [InvoiceSUM] FROM #DBObjectStats
END
GO
-- Execute stored procedure
EXEC TESTSUM
GO
And this work perfect and giving me right sum from all my DBs: 120 000$ ( 25 000 from SPA_PROD , 95 000 SPC_PROD and 0 (NULL) from SPB_PROD.
What I want to do:
I would like to parametrize, which allows me to choose date and databases. For example I want to choose SPA_PROD and SPB_PROD with date 2014-01-01 in another case I want all databases (SPA + SPB + SPC with another date.
Is this even possible? Any ideas?
I can use everything what gives me SQL Server 2012 and T-SQL. Maybe this technology offers me easiest way to do this.
I am also using SAP Crystal Reports to convert SQL output into a beautiful report.
Sorry for my English and I tried to describe to you my problem as far as I could. If you want any additional information which helps u to help me -> ask me :).
You can create a User-Defined Table Type:
CREATE TYPE DBTable AS TABLE
(
DBName VARCHAR(128)
);
You can use it as an input parameter of your stored procedure. As well as the date parameter.
CREATE PROCEDURE TESTSUM
#Databases DBTable READONLY
,#Date DATETIME
AS
BEGIN
...
...
...
You call it like this:
DECLARE #T AS DBTable;
DECLARE #D AS DATETIME = GETDATE();
INSERT INTO #T VALUES ('DB1', 'DB2', 'DB3')
EXEC TESTSUM #T, #D
maybe instead of
SELECT name
FROM MASTER.dbo.sysdatabases
use
SELECT name
FROM #temptable
and insert into #temptable specific db you want
Using your example I modified it to accept a string of database names (generated through you crystal reports select action). Then passing this string with the date in question to first validate the database exist and if online add the required union clause to the generated SQL code.
CREATE PROCEDURE TESTSUM
#DbNameS NVARCHAR(max)
,#Date DATETIME
AS
BEGIN
DECLARE #SQL NVARCHAR(MAX) = ''
/* ADD EXTRA ',' RO STRING ARRAY OF DATABASES */
SET #DbNameS = #DbNameS + ',';
DECLARE #L INT = LEN(#DbNameS);
DECLARE #D INT = 0;
DECLARE #LD INT = 1;
DECLARE #DBF VARCHAR(50);
DECLARE #ACTIVE INT = 0;
/* START SQL QUERY */
SET #SQL = 'SELECT SUM([InvoiceSUM]) AS [InvoiceSUM] FROM ( SELECT '''' AS DB, 0.00 AS [InvoiceSUM]' + CHAR(13)
/* LOOP THROUGH EACH DBF NAME PASSED CHECKING IF VALID AND ONLINE */
WHILE #D < #L
BEGIN
SET #D = CHARINDEX(',', #DbNameS,#LD);
IF #LD != #D
BEGIN
SET #DBF = SUBSTRING(#DbNameS,#LD,#D-#LD)
/* VALIDATE DBF IS VALID AND ACTIVE */
SELECT #ACTIVE = COUNT(*) FROM SYS.databases WHERE name = #DBF AND [state] = 0
IF #ACTIVE = 1
BEGIN
/*
BEGIN CODE TO UNION THE SUM RESULTS FOR EACH ACTIVE AND VALID DBF
TO MAKE IT WORK WITH SOME EXISTING DBF's ON MY SYSTEM I CHANGED THE SUMMARY CODE FOR TESTING
*/
SET #SQL = #SQL + 'UNION SELECT '''+ #DBF +''' AS DB, ISNULL(SUM( CAST(DVE AS DECIMAL(18,10)) ),0) AS [InvoiceSUM] FROM '+ #DBF + '.DBO.SO_MSTR WHERE CAST(RecordCreated AS DATE) = '''+ CAST(#Date AS VARCHAR(20)) + '''' + CHAR(13)
END;
END;
SET #LD = #D + 1;
END;
/* CLOSE OUT UNION SUMMARY QUERY */
SET #SQL = #SQL + ') AS DATA'
/* OUTPUT RESULTS */
EXEC SP_EXECUTESQL #SQL
END;
Crystal reports would effective be generating this code: EXEC TESTSUM 'SPA_PROD,SPB_PROD,SPC_PROD','12/09/2014'
I was wondering if someone could help me with creating a while loop to iterate through several databases to obtain data from one table from two columns. this is was I have done so far. nothing works because i do not know how to make the select statement work through each database with regards to the table that I am querying from each database (dbo.tbldoc)
DECLARE #Loop int
DECLARE #DBName varchar(300)
DECLARE #SQL varchar(max)
DECLARE #tableName VARCHAR(255)
SET #Loop = 1
SET #DBName = ''
WHILE #Loop = 1
BEGIN
SELECT [name] FROM sys.databases
WHERE [name] like 'z%' and create_date between '2010-10-17' and '2011-01-15'
ORDER BY [name]
SET #Loop = ##ROWCOUNT
IF #Loop = 0
BREAK
SET #SQL = ('USE ['+ #DBNAME +']')
IF EXISTS(SELECT [name] FROM sys.tables WHERE name != 'dbo.tbldoc' )
BEGIN
SELECT SUM(PGCOUNT), CREATED FROM **dbo.tbldoc**
END
ELSE
--BEGIN
PRINT 'ErrorLog'
END
I would consider sp_MSForEachDB which is a lot easier...
Edit:
EXEC sp_MSForEachDB 'USE [?]; IF DB_NAME() LIKE ''Z%%''
BEGIN
END
'
CREATE TABLE #T
(dbname sysname NOT NULL PRIMARY KEY,
SumPGCOUNT INT,
CREATED DATETIME)
DECLARE #Script NVARCHAR(MAX) = ''
SELECT #Script = #Script + '
USE ' + QUOTENAME(name) + '
IF EXISTS(SELECT * FROM sys.tables WHERE OBJECT_ID=OBJECT_ID(''dbo.tbldoc''))
INSERT INTO #T
SELECT db_name() AS dbname, SUM(PGCOUNT) AS SumPGCOUNT, CREATED
FROM dbo.tbldoc
GROUP BY CREATED;
'
FROM sys.databases
WHERE state=0 AND user_access=0 and has_dbaccess(name) = 1
AND [name] like 'z%' and create_date between '2010-10-17' and '2011-01-15'
ORDER BY [name]
IF (##ROWCOUNT > 0)
BEGIN
--PRINT #Script
EXEC (#Script)
SELECT * FROM #T
END
DROP TABLE #T
My code to search for data from more than one database would be:
use [master]
go
if object_id('tempdb.dbo.#database') is not null
drop TABLE #database
go
create TABLE #database(id INT identity primary key, name sysname)
go
set nocount on
insert into #database(name)
select name
from sys.databases
where name like '%tgsdb%' --CHANGE HERE THE FILTERING RULE FOR YOUR DATABASES!
and source_database_id is null
order by name
Select *
from #database
declare #id INT, #cnt INT, #sql NVARCHAR(max), #currentDb sysname;
select #id = 1, #cnt = max(id)
from #database
while #id <= #cnt
BEGIN
select #currentDb = name
from #database
where id = #id
set #sql = 'select Column1, Column2 from ' + #currentDb + '.dbo.Table1'
print #sql
exec (#sql);
print '--------------------------------------------------------------------------'
set #id = #id + 1;
END
go
DECLARE #Loop int
DECLARE #MaxLoop int
DECLARE #DBName varchar(300)
DECLARE #SQL varchar(max)
SET #Loop = 1
SET #DBName = ''
set nocount on
SET #MaxLoop = (select count([name]) FROM sys.databases where [name] like 'Z%')
WHILE #Loop <= #MaxLoop
BEGIN
SET #DBName = (select TableWithRowsNumbers.name from (select ROW_NUMBER() OVER (ORDER by [name]) as Row,[name] FROM sys.databases where [name] like 'Z%' ) TableWithRowsNumbers where Row = #Loop)
SET #SQL = 'USE [' + #DBName + ']'
exec (#SQL)
...
...
set #Loop = #Loop + 1
END
***Note: I didn't add the check if exists here.
I ended up writing one last week on the fly for some stuff I was doing.
Blog post here:
http://tsells.wordpress.com/2012/02/14/sql-server-database-iterator/
Here is the code.
SET NOCOUNT ON
GO
use master
go
Declare
#dbname nvarchar(500),
#variable1 int,
#variable2 int,
#variable3 int,
#totaldb int = 0,
#totaldbonserver int = 0,
#totaldbwithmatches int = 0
-- Get non system databases
Declare mycursor CURSOR for select name, database_id from SYS.databases where database_id > 4 order by name desc
open mycursor
fetch next from mycursor into #dbname, #variable1
while (##FETCH_STATUS <> -1)
BEGIN
DECLARE #ParmDefinition NVARCHAR(500)
Declare #mysql nvarchar(500) = 'select #variable2OUT = COUNT(*) from [' + #dbname + '].INFORMATION_SCHEMA.TABLES where Upper(TABLE_NAME) like ''MyTable''';
SET #ParmDefinition = N'#variable2OUT int OUTPUT'
set #totaldbonserver = #totaldbonserver + 1
Execute sp_executesql #mysql, #ParmDefinition, #variable2 OUTPUT
if #variable2 = 1
BEGIN
DECLARE #ParmDefinition2 NVARCHAR(500)
Declare #mysql2 nvarchar(500) = 'select #variable2OUT = COUNT(*) from [' + #dbname + '].dbo.MyTable';
SET #ParmDefinition2 = N'#variable2OUT int OUTPUT'
Execute sp_executesql #mysql2, #ParmDefinition2, #variable3 OUTPUT
set #totaldb = #totaldb + 1
if #variable3 > 1
BEGIN
Print #dbname + ' matched the criteria'
set #totaldbwithmatches = #totaldbwithmatches + 1
END
ELSE
Select 1
END
fetch next from mycursor into #dbname, #variable1
END
PRINT 'Total databases on server: '
Print #totaldbonserver
PRINT 'Total databases tested () : '
Print #totaldb
PRINT 'Total databases with matches: '
Print #totaldbwithmatches
CLOSE mycursor
DEALLOCATE mycursor
This doesn't use a loop. Hope this helps!
Note that "TABLE_OWNER" is that same as "SCHEMA Owner" and "TABLE_TYPE" will identify if the item is a table OR view.
--This will return all tables, table owners and table types for all database(s) that are NOT 'Offline'
--Offline database information will not appear
Declare #temp_table table(
DB_NAME varchar(max),
TABLE_OWNER varchar(max),
TABLE_NAME varchar(max),
TABLE_TYPE varchar(max),
REMARKS varchar(max)
)
INSERT INTO #temp_table (DB_NAME, TABLE_OWNER, TABLE_NAME, TABLE_TYPE,REMARKS)
EXECUTE master.sys.sp_MSforeachdb 'USE [?]; EXEC sp_tables'
SELECT DB_NAME, TABLE_OWNER, TABLE_NAME, TABLE_TYPE
FROM #temp_table
--Uncomment below if you are seaching for 1 database
--WHERE DB_NAME = '<Enter specific DB Name>'
--For all databases other than 'System Databases'
WHERE DB_NAME not in ('master','model','msdn','tempdb')
order by 1,2,3
You don't have to use a "USE DATABASE" statement. You can select from the particular database table by using a 3 part identifier as in:
select * from MyDatabase.dbo.MyTable