データとともに列名をエクスポートするために、bcpユーティリティを取得しようとする多くのハックを見てきました。テーブルをテキストファイルにダンプするだけなら、bcpに列ヘッダーを追加させる最も簡単な方法は何ですか?
現在使用しているbcpコマンドは次のとおりです。
bcp myschema.dbo.myTableout myTable.csv /SmyServer01 /c /t, -T
最も簡単なのは、queryout
オプションを使用し、union all
列リストを実際のテーブルコンテンツにリンクする
bcp "select 'col1', 'col2',... union all select * from myschema.dbo.myTableout" queryout myTable.csv /SmyServer01 /c /t, -T
例:
create table Question1355876
(id int, name varchar(10), someinfo numeric)
insert into Question1355876
values (1, 'a', 123.12)
, (2, 'b', 456.78)
, (3, 'c', 901.12)
, (4, 'd', 353.76)
このクエリは、ヘッダーを最初の行として情報を返します。 (数値のキャストに注意してください)
select 'col1', 'col2', 'col3'
union all
select cast(id as varchar(10)), name, cast(someinfo as varchar(28))
from Question1355876
Bcpコマンドは次のようになります。
bcp "select 'col1', 'col2', 'col3' union all select cast(id as varchar(10)), name, cast(someinfo as varchar(28)) from Question1355876" queryout myTable.csv /SmyServer01 /c /t, -T
このメソッドは、 [〜#〜] bcp [〜#〜] を使用して、行データとともに列名を自動的に出力します。
スクリプトは、列ヘッダー用に1つのファイルを書き込み(INFORMATION_SCHEMA.COLUMNS
テーブルから読み取り)、別のファイルにテーブルデータを追加します。
最終出力は、ヘッダーと行データを含むTableData.csv
に結合されます。上部の環境変数を置き換えて、サーバー、データベース、およびテーブル名を指定するだけです。
set BCP_EXPORT_SERVER=put_my_server_name_here
set BCP_EXPORT_DB=put_my_db_name_here
set BCP_EXPORT_TABLE=put_my_table_name_here
BCP "DECLARE @colnames VARCHAR(max);SELECT @colnames = COALESCE(@colnames + ',', '') + column_name from %BCP_EXPORT_DB%.INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='%BCP_EXPORT_TABLE%'; select @colnames;" queryout HeadersOnly.csv -c -T -S%BCP_EXPORT_SERVER%
BCP %BCP_EXPORT_DB%.dbo.%BCP_EXPORT_TABLE% out TableDataWithoutHeaders.csv -c -t, -T -S%BCP_EXPORT_SERVER%
set BCP_EXPORT_SERVER=
set BCP_EXPORT_DB=
set BCP_EXPORT_TABLE=
copy /b HeadersOnly.csv+TableDataWithoutHeaders.csv TableData.csv
del HeadersOnly.csv
del TableDataWithoutHeaders.csv
資格情報を提供する必要がある場合は、-Tオプションを-U my_username -P my_passwordに置き換えてください。
この方法には、INFORMATION_SCHEMA.COLUMNS
を使用して、常に列名をテーブルと同期させるという利点があります。欠点は、一時ファイルを作成することです。 Microsoftは、これをサポートするためにbcpユーティリティを実際に修正する必要があります。
優れた代替手段はSqlCmdです。これにはヘッダーが含まれますが、人間が読みやすいようにデータの周囲にスペースパディングを追加するという欠点があります。 SqlCmdをGnuWin32 sed(ストリーム編集)ユーティリティと組み合わせて、結果をクリーンアップできます。これが私のために働いた例ですが、それが防弾であることを保証することはできませんが。
まず、データをエクスポートします。
sqlcmd -S Server -i C:\Temp\Query.sql -o C:\Temp\Results.txt -s" "
-s" "
は二重引用符で囲まれたタブ文字です。バッチファイルを介してこのコマンドを実行する必要があることがわかりました。そうしないと、Windowsコマンドプロンプトはタブを自動補完コマンドとして扱い、タブの代わりにファイル名を置き換えます。
Query.sqlに含まれている場合:
SELECT name, object_id, type_desc, create_date
FROM MSDB.sys.views
WHERE name LIKE 'sysmail%'
その後、Results.txtに次のようなものが表示されます。
name object_id type_desc create_date ------------------------------------------- ----------- ------------------- ----------------------- sysmail_allitems 2001442204 VIEW 2012-07-20 17:38:27.820 sysmail_sentitems 2017442261 VIEW 2012-07-20 17:38:27.837 sysmail_unsentitems 2033442318 VIEW 2012-07-20 17:38:27.850 sysmail_faileditems 2049442375 VIEW 2012-07-20 17:38:27.860 sysmail_mailattachments 2097442546 VIEW 2012-07-20 17:38:27.933 sysmail_event_log 2129442660 VIEW 2012-07-20 17:38:28.040 (6 rows affected)
次に、sedを使用してテキストを解析します。
sed -r "s/ +\t/\t/g" C:\Temp\Results.txt | sed -r "s/\t +/\t/g" | sed -r "s/(^ +| +$)//g" | sed 2d | sed $d | sed "/^$/d" > C:\Temp\Results_New.txt
2d
コマンドは、2番目の行である$d
コマンドは最後の行を削除することを意味し、"/^$/d"
は、空白行を削除します。
クリーンアップされたファイルは次のようになります(ただし、タブを|
ここで視覚化できます):
name|object_id|type_desc|create_date sysmail_allitems|2001442204|VIEW|2012-07-20 17:38:27.820 sysmail_sentitems|2017442261|VIEW|2012-07-20 17:38:27.837 sysmail_unsentitems|2033442318|VIEW|2012-07-20 17:38:27.850 sysmail_faileditems|2049442375|VIEW|2012-07-20 17:38:27.860 sysmail_mailattachments|2097442546|VIEW|2012-07-20 17:38:27.933 sysmail_event_log|2129442660|VIEW|2012-07-20 17:38:28.040
私は最近これを行う方法を考えていましたが、一番上の最も人気のあるソリューションが好きですが、スクリプトに入力したエイリアスの名前にする必要があるため、私にはうまくいきませんでしたので、いくつかのバッチファイルを使用しました(同僚の助けを借りて)カスタムテーブル名を実現します。
Bcpを開始するバッチファイルには、テンプレートファイルとヘッダー名をマージする別のスクリプトと、次のコードを使用してbcpでエクスポートしたファイルを実行するスクリプトの下部に行があります。これが私の状況にあった他の誰かを助けることを願っています。
echo Add headers from template file to exported sql files....
Echo School 0031
copy e:\genin\templates\TEMPLATE_Courses.csv + e:\genin\0031\courses0031.csv e:\genin\finished\courses0031.csv /b
私は同じ問題を抱えていました。 SQLサーバーのbcpユーティリティを使用して列ヘッダーをエクスポートする必要がありました。この方法で、データを含むテーブル「ヘッダー」を同じエクスポートファイルに一度にエクスポートしました。
DECLARE @table_name VARCHAR(50)= 'mytable' DECLARE @columnHeader VARCHAR(8000) SELECT @columnHeader = COALESCE(@ columnHeader + '、') '' ' '' '+ column_name +' '' 'FROM Nal2013.INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @ table_name SELECT @raw_sql =' bcp "SELECT '+ @columnHeader +' UNION ALL SELECT * FROM mytable"クエリアウトc:\datafile.csv -c -t、-T -S '+ @@ servername EXEC xp_cmdshell @raw_sql
ハッピーコーディング:)
トリックを行う非常にシンプルなストアドプロシージャを次に示します。
CREATE PROCEDURE GetBCPTable
@table_name varchar(200)
AS
BEGIN
DECLARE @raw_sql nvarchar(3000)
DECLARE @columnHeader VARCHAR(8000)
SELECT @columnHeader = COALESCE(@columnHeader+',' ,'')+ ''''+column_name +'''' FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @table_name
DECLARE @ColumnList VARCHAR(8000)
SELECT @ColumnList = COALESCE(@ColumnList+',' ,'')+ 'CAST('+column_name +' AS VARCHAR)' FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @table_name
SELECT @raw_sql = 'SELECT '+ @columnHeader +' UNION ALL SELECT ' + @ColumnList + ' FROM ' + @table_name
--PRINT @raw_SQL
EXECUTE sp_executesql @raw_sql
END
GO
私が知っているすべてから、BCPはデータのみをエクスポートします-列名を含むヘッダー行をエクスポートする方法はないと思います。
これを解決するために見られる一般的な手法の1つは、エクスポートに実際のデータのビューを使用することです。これは、基本的に2つのステートメントでUNION ALLを実行します。
そして、基礎となるデータテーブルを直接ではなく、そのビューでbcpを使用します。
マーク
みんなのバージョンは少し違うことをします。これは私が長年にわたって開発したバージョンです。このバージョンは、私が遭遇したすべての問題を説明しているようです。データセットをテーブルに入力し、テーブル名をこのストアドプロシージャに渡すだけです。
このストアドプロシージャは次のように呼び出します。
EXEC @return_value = *DB_You_Create_The_SP_In*.[dbo].[Export_CSVFile]
@DB = N'*YourDB*',
@TABLE_NAME = N'*YourTable*',
@Dir = N'*YourOutputDirectory*',
@File = N'*YourOutputFileName*'
他にも2つの変数があります。
これにより、ストアドプロシージャが作成されます。
CREATE PROCEDURE [dbo].[Export_CSVFile]
(@DB varchar(128),@TABLE_NAME varchar(128), @Dir varchar(255), @File varchar(250),@NULLBLANKS bit=1,@IncludeHeader bit=1)
AS
DECLARE @CSVHeader varchar(max)='' --CSV Header
, @CmdExc varchar(max)='' --EXEC commands
, @SQL varchar(max)='' --SQL Statements
, @COLUMN_NAME varchar(128)='' --Column Names
, @DATA_TYPE varchar(15)='' --Data Types
DECLARE @T table (COLUMN_NAME varchar(128),DATA_TYPE varchar(15))
--BEGIN Ensure Dir variable has a backslash as the final character
IF NOT RIGHT(@Dir,1) = '\' BEGIN SET @Dir=@Dir+'\' END
--END
--BEGIN Drop TEMP Table IF Exists
SET @SQL='IF (EXISTS (SELECT * FROM '+@DB+'.INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = ''TEMP_'+@TABLE_NAME+''')) BEGIN EXEC(''DROP TABLE ['+@DB+'].[dbo].[TEMP_'+@TABLE_NAME+']'') END'
EXEC(@SQL)
--END
SET @SQL='SELECT COLUMN_NAME,DATA_TYPE FROM '+@DB+'.INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME ='''+@TABLE_NAME+''' ORDER BY ORDINAL_POSITION'
INSERT INTO @T
EXEC (@SQL)
SET @SQL=''
WHILE exists(SELECT * FROM @T)
BEGIN
SELECT top(1) @DATA_TYPE=DATA_TYPE,@COLUMN_NAME=COLUMN_NAME FROM @T
IF @DATA_TYPE LIKE '%char%' OR @DATA_TYPE LIKE '%text'
BEGIN
IF @NULLBLANKS = 1
BEGIN
SET @SQL+='CASE PATINDEX(''%[0-9,a-z]%'','+@COLUMN_NAME+') WHEN ''0'' THEN NULL ELSE ''"''+RTRIM(LTRIM('+@COLUMN_NAME+'))+''"'' END AS ['+@COLUMN_NAME+'],'
END
ELSE
BEGIN
SET @SQL+='''"''+RTRIM(LTRIM('+@COLUMN_NAME+'))+''"'' AS ['+@COLUMN_NAME+'],'
END
END
ELSE
BEGIN SET @SQL+=@COLUMN_NAME+',' END
SET @CSVHeader+='"'+@COLUMN_NAME+'",'
DELETE top(1) @T
END
IF LEN(@CSVHeader)>1 BEGIN SET @CSVHeader=RTRIM(LTRIM(LEFT(@CSVHeader,LEN(@CSVHeader)-1))) END
IF LEN(@SQL)>1 BEGIN SET @SQL= 'SELECT '+ LEFT(@SQL,LEN(@SQL)-1) + ' INTO ['+@DB+'].[dbo].[TEMP_'+@TABLE_NAME+'] FROM ['+@DB+'].[dbo].['+@TABLE_NAME+']' END
EXEC(@SQL)
IF @IncludeHeader=0
BEGIN
--BEGIN Create Data file
SET @CmdExc ='BCP "'+@DB+'.dbo.TEMP_'+@TABLE_NAME+'" out "'+@Dir+'Data_'+@TABLE_NAME+'.csv" /c /t, -T'
EXEC master..xp_cmdshell @CmdExc
--END
SET @CmdExc ='del '+@Dir+@File EXEC master..xp_cmdshell @CmdExc
SET @CmdExc ='ren '+@Dir+'Data_'+@TABLE_NAME+'.csv '+@File EXEC master..xp_cmdshell @CmdExc
END
else
BEGIN
--BEGIN Create Header and main file
SET @CmdExc ='echo '+@CSVHeader+'> '+@Dir+@File EXEC master..xp_cmdshell @CmdExc
--END
--BEGIN Create Data file
SET @CmdExc ='BCP "'+@DB+'.dbo.TEMP_'+@TABLE_NAME+'" out "'+@Dir+'Data_'+@TABLE_NAME+'.csv" /c /t, -T'
EXEC master..xp_cmdshell @CmdExc
--END
--BEGIN Merge Data File With Header File
SET @CmdExc = 'TYPE '+@Dir+'Data_'+@TABLE_NAME+'.csv >> '+@Dir+@File EXEC master..xp_cmdshell @CmdExc
--END
--BEGIN Delete Data File
SET @CmdExc = 'DEL /q '+@Dir+'Data_'+@TABLE_NAME+'.csv' EXEC master..xp_cmdshell @CmdExc
--END
END
--BEGIN Drop TEMP Table IF Exists
SET @SQL='IF (EXISTS (SELECT * FROM '+@DB+'.INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = ''TEMP_'+@TABLE_NAME+''')) BEGIN EXEC(''DROP TABLE ['+@DB+'].[dbo].[TEMP_'+@TABLE_NAME+']'') END'
EXEC(@SQL)
1つのcteビューとbcpコードを含む1つのバッチファイルでこの問題を解決できるはずです。最初にビューを作成します。比較的簡単なので、一時テーブルを作成しなかったので、通常は
CREATE VIEW [dbo].[vwxMySAMPLE_EXTRACT_COLUMNS]
AS
WITH MYBCP_CTE (COLUMN_NM, ORD_POS, TXT)
AS
( SELECT COLUMN_NAME
, ORDINAL_POSITION
, CAST(COLUMN_NAME AS VARCHAR(MAX))
FROM [INFORMATION_SCHEMA].[COLUMNS]
WHERE TABLE_NAME = 'xMySAMPLE_EXTRACT_NEW'
AND ORDINAL_POSITION = 1
UNION ALL
SELECT V.COLUMN_NAME
, V.ORDINAL_POSITION
, CAST(C.TXT + '|' + V.COLUMN_NAME AS VARCHAR(MAX))
FROM [INFORMATION_SCHEMA].[COLUMNS] V INNER JOIN MYBCP_CTE C
ON V.ORDINAL_POSITION = C.ORD_POS+1
AND V.ORDINAL_POSITION > 1
WHERE TABLE_NAME = 'xMySAMPLE_EXTRACT_NEW'
)
SELECT CC.TXT
FROM MYBCP_CTE CC INNER JOIN ( SELECT MAX(ORD_POS) AS MX_CNT
FROM MYBCP_CTE C
) SC
ON CC.ORD_POS = SC.MX_CNT
次に、バッチファイルを作成します。これをTempディレクトリで作成しましたが、怠け者です。
cd\
CD "C:\Program Files\Microsoft SQL Server\110\Tools\Binn"
set buildhour=%time: =0%
set buildDate=%DATE:~4,10%
set backupfiledate=%buildDate:~6,4%%buildDate:~0,2%%buildDate:~3,2%%time:~0,2%%time:~3,2%%time:~6,2%
echo %backupfiledate%
pause
上記のコードは、ファイルの末尾に追加する日付を作成するだけです。次に、再帰cteを表示する最初のbcpステートメントで、すべてを連結します。
bcp "SELECT * FROM [dbo].[vwxMYSAMPLE_EXTRACT_COLUMNS] OPTION (MAXRECURSION 300)" queryout C:\Temp\Col_NM%backupfiledate%.txt -c -t"|" -S MYSERVERTOLOGINTO -T -q
bcp "SELECT * FROM [myDBName].[dbo].[vwxMYSAMPLE_EXTRACT_NEW] " queryout C:\Temp\3316_PHYSDATA_ALL%backupfiledate%.txt -c -t"|" -S MYSERVERTOLOGINTO -T -q
次に、コピーコマンドを使用してそれらをマージします
copy C:\Temp\Col_NM%backupfiledate%.txt + C:\Temp\3316_PHYSDATA_ALL%backupfiledate%.txt C:\Temp\3316_PHYSDATA_ALL%backupfiledate%.csv
準備完了
Sqlcmdの最新バージョンでは、-w
オプションは、フィールド値の後の余分なスペースを削除します。ただし、文字列を引用符で囲まないため、カンマを含むフィールド値をインポートするときにCSVで問題になる可能性があります。
以前見たものに基づいたバージョンを入手しました。 CSVまたはTXTとしてエクスポートファイルを作成するのに非常に役立ちました。 ##一時テーブルにテーブルを保存しています:
IF OBJECT_ID('tempdb..##TmpExportFile') IS NOT NULL
DROP TABLE ##TmpExportFile;
DECLARE @columnHeader VARCHAR(8000)
DECLARE @raw_sql nvarchar(3000)
SELECT
* INTO ##TmpExportFile
------ FROM THE TABLE RESULTS YOU WANT TO GET
------ COULD BE A TABLE OR A TEMP TABLE BASED ON INNER JOINS
------ ,ETC.
FROM TableName -- optional WHERE ....
DECLARE @table_name VARCHAR(50) = '##TmpExportFile'
SELECT
@columnHeader = COALESCE(@columnHeader + ',', '') + '''[' + c.name + ']''' + ' as ' + '' + c.name + ''
FROM tempdb.sys.columns c
INNER JOIN tempdb.sys.tables t
ON c.object_id = t.object_id
WHERE t.NAME = @table_name
print @columnheader
DECLARE @ColumnList VARCHAR(max)
SELECT
@ColumnList = COALESCE(@ColumnList + ',', '') + 'CAST([' + c.name + '] AS CHAR(' + LTRIM(STR(max_length)) + '))'
FROM tempdb.sys.columns c
INNER JOIN tempdb.sys.tables t
ON c.object_id = t.object_id
WHERE t.name = @table_name
print @ColumnList
--- CSV FORMAT
SELECT
@raw_sql = 'bcp "SELECT ' + @columnHeader + ' UNION all SELECT ' + @ColumnList + ' FROM ' + @table_name + ' " queryout \\networkdrive\networkfolder\datafile.csv -c -t, /S' + ' SQLserverName /T'
--PRINT @raw_sql
EXEC xp_cmdshell @raw_sql
--- TXT FORMAT
SET @raw_sql = 'bcp "SELECT ' + @columnHeader + ' UNION all SELECT ' + @ColumnList + ' FROM ' + @table_name + ' " queryout \\networkdrive\networkfolder\MISD\datafile.txt /c /S'+ ' SQLserverName /T'
EXEC xp_cmdshell @raw_sql
DROP TABLE ##TmpExportFile
少しのPowerShellスクリプト
sqlcmd -Q "set nocount on select top 0 * from [DB].[schema].[table]" -o c:\temp\header.txt
bcp [DB].[schema].[table] out c:\temp\query.txt -c -T -S BRIZA
Get-Content c:\temp\*.txt | Set-Content c:\temp\result.txt
Remove-Item c:\temp\header.txt
Remove-Item c:\temp\query.txt
連結がtxtファイル名に従う(アルファベット順で)警告
以下のコードでこれを成功裏に達成しました。 SQL Serverの新しいクエリウィンドウに以下のコードを入れて試してください
CREATE TABLE tempDBTableDetails ( TableName VARCHAR(500), [RowCount] VARCHAR(500), TotalSpaceKB VARCHAR(500),
UsedSpaceKB VARCHAR(500), UnusedSpaceKB VARCHAR(500) )
-- STEP 1 ::
DECLARE @cmd VARCHAR(4000)
INSERT INTO tempDBTableDetails
SELECT 'TableName', 'RowCount', 'TotalSpaceKB', 'UsedSpaceKB', 'UnusedSpaceKB'
INSERT INTO tempDBTableDetails
SELECT
S.name +'.'+ T.name as TableName,
Convert(varchar,Cast(SUM(P.rows) as Money),1) as [RowCount],
Convert(varchar,Cast(SUM(a.total_pages) * 8 as Money),1) AS TotalSpaceKB,
Convert(varchar,Cast(SUM(a.used_pages) * 8 as Money),1) AS UsedSpaceKB,
(SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
FROM sys.tables T
INNER JOIN sys.partitions P ON P.OBJECT_ID = T.OBJECT_ID
INNER JOIN sys.schemas S ON T.schema_id = S.schema_id
INNER JOIN sys.allocation_units A ON p.partition_id = a.container_id
WHERE T.is_ms_shipped = 0 AND P.index_id IN (1,0)
GROUP BY S.name, T.name
ORDER BY SUM(P.rows) DESC
-- SELECT * FROM [FIINFRA-DB-SIT].dbo.tempDBTableDetails ORDER BY LEN([RowCount]) DESC
SET @cmd = 'bcp "SELECT * FROM [FIINFRA-DB-SIT].dbo.tempDBTableDetails ORDER BY LEN([RowCount]) DESC" queryout "D:\Milind\export.xls" -U sa -P dbowner -c'
Exec xp_cmdshell @cmd
--DECLARE @HeaderCmd VARCHAR(4000)
--SET @HeaderCmd = 'SELECT ''TableName'', ''RowCount'', ''TotalSpaceKB'', ''UsedSpaceKB'', ''UnusedSpaceKB'''
exec master..xp_cmdshell 'BCP "SELECT ''TableName'', ''RowCount'', ''TotalSpaceKB'', ''UsedSpaceKB'', ''UnusedSpaceKB''" queryout "d:\milind\header.xls" -U sa -P dbowner -c'
exec master..xp_cmdshell 'copy /b "d:\Milind\header.xls"+"d:\Milind\export.xls" "d:/Milind/result.xls"'
exec master..xp_cmdshell 'del "d:\Milind\header.xls"'
exec master..xp_cmdshell 'del "d:\Milind\export.xls"'
DROP TABLE tempDBTableDetails
同じことをする別の方法を以下で見つけてください。また、このプロシージャは、テーブルにアクセスする必要がある場合に備えて、パラメータにスキーマ名を取ります。
CREATE PROCEDURE Export_Data_NBA
@TableName nchar(50),
@TableSchema nvarchar(50) = ''
AS
DECLARE @TableToBeExported as nvarchar(50);
DECLARE @OUTPUT TABLE (col1 nvarchar(max));
DECLARE @colnamestable VARCHAR(max);
select @colnamestable = COALESCE(@colnamestable, '') +COLUMN_NAME+ ','
from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = @TableName
order BY ORDINAL_POSITION
SELECT @colnamestable = LEFT(@colnamestable,DATALENGTH(@colnamestable)-1)
INSERT INTO @OUTPUT
select @colnamestable
DECLARE @selectstatement VARCHAR(max);
select @selectstatement = COALESCE(@selectstatement, '') + 'Convert(nvarchar(100),'+COLUMN_NAME+')+'',''+'
from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = @TableName
order BY ORDINAL_POSITION
SELECT @selectstatement = LEFT(@selectstatement,DATALENGTH(@selectstatement)-1)
DECLARE @sqlstatment as nvarchar(max);
SET @TableToBeExported = @TableSchema+'.'+@TableToBeExported
SELECT @sqlstatment = N'Select '+@selectstatement+N' from '+@TableToBeExported
INSERT INTO @OUTPUT
exec sp_executesql @stmt = @sqlstatment
SELECT * from @OUTPUT