1

I tried using SSMS but it only lets me export one file at a time and I'd prefer not to create an SSIS package. Is it possible to do this in PowerShell?

I need the headers of each table in the file as well not just the data.

1

3 Answers 3

1

I have used T-SQL.

I don't generate tab delimited files, but csv files.

In preparation to this task:

  1. open ssms as administrator
  2. check in your computer what is the path to the bcp.exe command - on my local machine it is C:\Program Files (x86)\Microsoft SQL Server\Client SDK\ODBC\130\Tools\Binn\ - not that you actually need it but I always do it this way
  3. make sure that you have full permissions and the sql server has full permissions in the folder that you are going to create the files. this you can achieve using powershell
  4. you would have to open a few things in the sql configuration, save all the settings as they are, so that you can make sure you leave them as they were after your finish

``

USE [master] 
GO 

EXEC master.dbo.sp_MSset_oledb_prop N'Microsoft.ACE.OLEDB.12.0',
                                    N'AllowInProcess', 1 
GO 
EXEC master.dbo.sp_MSset_oledb_prop N'Microsoft.ACE.OLEDB.12.0', 
                                    N'DynamicParameters', 1 
GO 
sp_configure
sp_configure 'Ad Hoc Distributed Queries',1
sp_configure 'xp_cmdshell',1
RECONFIGURE
  1. pay attention to the connectivity to your sql server instance

    this is how my server is called:

``

SELECT @@SERVERNAME
--VRINDAVANA\SQL2019
--my database is called [Radhe Shyam]
  1. I am going to use a cursor to read through the tables

the tables:

SELECT NAME  FROM SYS.TABLES ORDER BY NAME DESC

enter image description here

The script

go
USE [RADHE SHYAM]
go

DECLARE @bcp_cmd1 VARCHAR(1000);
DECLARE @exe_path1 VARCHAR(200) =
' cd C:\Program Files (x86)\Microsoft SQL Server\Client SDK\ODBC\130\Tools\Binn\ & ';
declare @name nvarchar(150)

declare ttables CURSOR FOR
       SELECT NAME  FROM SYS.TABLES ORDER BY NAME DESC


OPEN ttables  
FETCH NEXT FROM ttables INTO @name


WHILE @@FETCH_STATUS = 0  
BEGIN  
        
        print @name
        SET @bcp_cmd1 = @exe_path1 +' BCP.EXE "SELECT * FROM [RADHE SHYAM].dbo.' 
                        + @name + '" queryout  "D:\DATA\'  
                        + @name +   '.CSV" -S VRINDAVANA\SQL2019 -w -T -t; ';

        EXEC master..xp_cmdshell @bcp_cmd1;
        FETCH NEXT FROM ttables INTO @name     

END 

CLOSE ttables  
DEALLOCATE ttables 

The output

enter image description here

The files:

enter image description here

Inside the files:

enter image description here

Now using bcp with tab delimiter:

Replacing the following line in the script above

                    + @name +   '.CSV" -S VRINDAVANA\SQL2019 -w -T -t; ';

WITH

                    + @name +   '.CSV" -S VRINDAVANA\SQL2019 -w -T -t"\t" ';

Gets a tab delimiter to separate the columns in the generated file.

Here is the new tab delimited csv file generation script:

go
USE [RADHE SHYAM]
go

DECLARE @bcp_cmd1 VARCHAR(1000);
DECLARE @exe_path1 VARCHAR(200) =
' cd C:\Program Files (x86)\Microsoft SQL Server\Client SDK\ODBC\130\Tools\Binn\ & ';
declare @name nvarchar(150)

declare ttables CURSOR FOR
   SELECT NAME  FROM SYS.TABLES ORDER BY NAME DESC


OPEN ttables  
FETCH NEXT FROM ttables INTO @name


WHILE @@FETCH_STATUS = 0  
BEGIN  
    
    
    print @name
    SET @bcp_cmd1 = @exe_path1 +' BCP.EXE "SELECT * FROM [RADHE SHYAM].dbo.' 
                    + @name + '" queryout  "D:\DATA\'  
                    + @name +   '.CSV" -S VRINDAVANA\SQL2019 -w -T -t"\t" ';

    EXEC master..xp_cmdshell @bcp_cmd1;
    FETCH NEXT FROM ttables INTO @name 


END 

CLOSE ttables  
DEALLOCATE ttables 

And a picture of the new files generated:

enter image description here

Note that when opening in excel each table field goes into a different excel column and in the text file, there is a tab space between the fields.

1
1

Further to my other answer which works fine but does not include the headers.

this one does. Both use the BCP utility.

It is wrapped in a cursor that reads all the tables in the current database.

It works for image and uniqueidentifiers data types.

I have tested it in the msdb database.

--=================================
-- script to export all tables in a database
-- using bcp
-- tab delimited columns
-- include column names in the first row
-- deals with image and uniqueidentifiers data types
-- marcello miorelli v.20221020
--=================================

declare @name nvarchar(150)
declare @tschema nvarchar(150)

declare ttables CURSOR read_only fast_forward FOR
SELECT table_schema=schema_name(schema_id), NAME  
  FROM SYS.TABLES ORDER BY NAME DESC


OPEN ttables  
FETCH NEXT FROM ttables INTO @tschema ,@name


WHILE @@FETCH_STATUS = 0  
BEGIN  


print @name


        --------------------------------------------------------------------------------
        IF object_id('tempdb..##Radhe_Shyam',N'U') IS NOT NULL
           DROP TABLE ##Radhe_Shyam

        DECLARE @table_schema nvarchar(108)=@tschema --table schema
        DECLARE @table_name varchar(108)=@name--which needs to be exported
        DECLARE @fileName varchar(1008)='RadheRadhe'


        DECLARE @bcp_cmd1 VARCHAR(1000);
        DECLARE @exe_path1 VARCHAR(200) = ' cd C:\Program Files (x86)\Microsoft SQL Server\Client SDK\ODBC\130\Tools\Binn\ & ';

        DECLARE @columnHeader VARCHAR(4000)
        SELECT @columnHeader=NULL

        SELECT @columnHeader = COALESCE(@columnHeader+',' ,'')
               + ''''+column_name +''''  
          FROM INFORMATION_SCHEMA.COLUMNS 
          WHERE TABLE_NAME = @table_name
           AND TABLE_SCHEMA = @table_schema

        DECLARE @ColumnList VARCHAR(max)
        SELECT @ColumnList=NULL
        SELECT @ColumnList = COALESCE(@ColumnList+',' ,'')
               + CASE WHEN r.data_type = 'image' 
                      THEN 'CAST(CAST('+r.column_name +' AS varbinary(max))AS NVARCHAR(MAX))'
                      ELSE 'CAST('+r.column_name +' AS NVARCHAR(MAX))' 
                 END
               + r.column_name 
          FROM INFORMATION_SCHEMA.COLUMNS r
          WHERE r.TABLE_NAME = @table_name
           AND r.TABLE_SCHEMA = @table_schema

        DECLARE @tempRaw_sql nvarchar(max)
        SELECT @tempRaw_sql = N'SELECT ' 
                              + @ColumnList + N' into ##Radhe_Shyam FROM ' 
                              + @table_schema  + N'.' + @table_name 
        PRINT @tempRaw_sql
        EXECUTE sp_executesql  @tempRaw_sql

        SELECT @fileName =  @table_schema  + '_' + @table_name 

        DECLARE @raw_sql nvarchar(max)
        SELECT @raw_sql = 'SELECT  '+ @columnHeader 
                           +' UNION ALL SELECT * FROM ##Radhe_Shyam'
        PRINT @raw_SQL
        SET @bcp_cmd1 = @exe_path1 +' BCP.EXE ' + '"' 
                       + @raw_SQL + '"' 
                       + ' queryout "d:\data\'+ @fileName 
                       +'.csv" -t"\t" -T -w -S '+ @@servername

        print  @bcp_cmd1 

        EXEC xp_cmdshell @bcp_cmd1 

        --------------------------------------------------------------------------------

FETCH NEXT FROM ttables INTO  @tschema ,@name


END 

CLOSE ttables  
DEALLOCATE ttables 

I have tested this script in several databases with a good number of tables and rows in those tables.

enter image description here

Inside of the generated files it looks like this:

enter image description here

3
  • Explicit conversion from data type image to varchar(max) is not allowed. Oct 20, 2022 at 14:17
  • That was solved by casting to varbinary first. before casting to nvarchar(max) - Select cast(cast(imageColumn as varbinary(max)) as varchar(max)) From myTable Oct 20, 2022 at 14:52
  • 1
    Thank You! I accepted your other answer because Stack Exchange only lets me accept one.
    – JTD2021
    Oct 21, 2022 at 3:37
0

I'm a bit annoyed I don't know of a dbatools builtin for this but this should do you in a pinch:

$connectionSplat = @{
    sqlInstance = "localhost"
    database = "msdb"
}

$folder = New-Item -Type Directory -Path $HOME/Desktop/TableExport -Force

Get-DbaDbTable @connectionSplat | ForEach-Object {
    $data = Invoke-DbaQuery @connectionSplat -Query "select * from [$($_.schema)].[$($_.name)]" 
    $data = $data | Select-Object * -ExcludeProperty 'RowError','RowState','Table','ItemArray','HasErrors' 

    if($data.Count -gt 0){
        $data | Export-Csv "$($folder.FullName)/$($_.schema).$($_.name).tsv" -Delimiter "`t"}
    }
}

You need to install and import the dbatools module if you don't already have it. And if you're on PowerShell 6 or 7, I recommend the option -UseQuotes AsNeeded for Export-Csv.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.