Sometimes you want to dump the data from all the tables in a database into files. There is really no fast and easy way to do this. Fortunately it is very easy to roll your own solution. Let’s look at what we need to do

1) we need to grab all the tables in the database

2) we need to make sure that the table names are valid

3) we need to specify the output directory

4) we need to make sure that the file names are valid

5) we need to specify how we are connecting to SQL Server

We need to grab all the tables in the database

The query to grab all the names is

SELECT name FROM sys.tables

However if you use schemas then that won’t work, you need to do the following

SELECT SCHEMA_NAME(SCHEMA_ID),name 
FROM sys.tables

The reason for this is that you can have the same table name in different schemas, you would only get the one in the default schema

We need to make sure that the table names are valid

Sometimes you have table names that have spaces in them or start perhaps with a number. If you have tables like that, you have to put brackets around it. One way to put brackets around tables names is to just do something like this '[' + name + ']' another way is to use the QUOTENAME function

SELECT   QUOTENAME(SCHEMA_NAME(SCHEMA_ID))+ '.'
+  QUOTENAME(name) FROM sys.tables

We need to specify the output directory

You need to tell bcp where to dump the files

We need to make sure that the file names are valid

Windows does not allow for certain characters in file names

< (less than) > (greater than)

(colon)

” (double quote)

/ (forward slash)

(backslash)

| (vertical bar or pipe)

? (question mark)

  • (asterisk)

If you have to give the files to be imported on a Linux/unix systems then you want to eliminate spaces as well

In that case you end up with something like this

SELECT    REPLACE(SCHEMA_NAME(schema_id),' ','') + '_' 
+  REPLACE(name,' ','') 
+  QUOTENAME(name) FROM sys.tables

We need to specify how we are connecting to SQL Server

You can use password and username to connect to SQL Server or you can use a trusted connections

Putting it all together

Here is the complete query

SELECT 'EXEC xp_cmdshell ''bcp '           --bcp
+  QUOTENAME(DB_NAME())+ '.'               --database name
+  QUOTENAME(SCHEMA_NAME(SCHEMA_ID))+ '.'  -- schema
+  QUOTENAME(name)						   -- table
+ ' out c:temp'                          -- output directory
+  REPLACE(SCHEMA_NAME(schema_id),' ','') + '_' 
+  REPLACE(name,' ','')                    -- file name
+ '.txt -T -c'''   -- extension, security 
FROM sys.tables

Running that query will give you something like the following

EXEC xp_cmdshell 'bcp [AdventureWorks2012].[Production].[ScrapReason] out c:tempProduction_ScrapReason.txt -T -c'

EXEC xp_cmdshell 'bcp [AdventureWorks2012].[HumanResources].[Shift] out c:tempHumanResources_Shift.txt -T -c'

EXEC xp_cmdshell 'bcp [AdventureWorks2012].[Production].[ProductCategory] out c:tempProduction_ProductCategory.txt -T -c'

EXEC xp_cmdshell 'bcp [AdventureWorks2012].[Purchasing].[ShipMethod] out c:tempPurchasing_ShipMethod.txt -T -c'

EXEC xp_cmdshell 'bcp [AdventureWorks2012].[Production].[ProductCostHistory] out c:tempProduction_ProductCostHistory.txt -T -c'

You can now take that and run it. When you run it, you will see the following output

NULL

Starting copy…

NULL

32 rows copied.

Network packet size (bytes): 4096

Clock Time (ms.) Total : 1 Average : (32000.00 rows per sec.)

NULL

Sometines you don’t want to see that output,In that case we need to suppress xp_cmdshell output, you do this by adding ,no_output at the end

SELECT 'EXEC xp_cmdshell ''bcp '           --bcp
+  QUOTENAME(DB_NAME())+ '.'               --database name
+  QUOTENAME(SCHEMA_NAME(SCHEMA_ID))+ '.'  -- schema
+  QUOTENAME(name)						   -- table
+ ' out c:temp'                          -- output directory
+  REPLACE(SCHEMA_NAME(schema_id),' ','') + '_' 
+  REPLACE(name,' ','')                    -- file name
+ '.txt -T -c'',no_output'   -- extension, security, no output 
FROM sys.tables

Now you get something like the following

EXEC xp_cmdshell 'bcp [AdventureWorks2012].[Production].[ScrapReason] out c:tempProduction_ScrapReason.txt -T -c',no_output

EXEC xp_cmdshell 'bcp [AdventureWorks2012].[HumanResources].[Shift] out c:tempHumanResources_Shift.txt -T -c',no_output

EXEC xp_cmdshell 'bcp [AdventureWorks2012].[Production].[ProductCategory] out c:tempProduction_ProductCategory.txt -T -c',no_output

EXEC xp_cmdshell 'bcp [AdventureWorks2012].[Purchasing].[ShipMethod] out c:tempPurchasing_ShipMethod.txt -T -c',no_output

There you have it, a quick and dirty version to dump all the tables into files.

You can of course enhance this by creating a proc where you can specify only a certain schema, delimiters, how to connect etc etc

If you don’t want to use xp_cmdshell, you can also dump the results without the xp_cmdshell part into a BAT file and call it from DOS or PowerShell

That query would look like this

SELECT 'bcp '           --bcp
+  QUOTENAME(DB_NAME())+ '.'               --database name
+  QUOTENAME(SCHEMA_NAME(SCHEMA_ID))+ '.'  -- schema
+  QUOTENAME(name)						   -- table
+ ' out c:temp'                          -- output directory
+  REPLACE(SCHEMA_NAME(schema_id),' ','') + '_' 
+  REPLACE(name,' ','')                    -- file name
+ '.txt -T -c'   -- extension, security, 
FROM sys.tables