È possibile generare un file csv da una stored procedure in SQL Server? Ho creato la mia stored procedure e voglio memorizzare alcuni risultati come csv, qualcuno sa come ottenere questo?Come produrre un file di output csv dalla stored procedure in SQL Server
risposta
Ecco un paio di link con un modo per farlo:
Questo script esporta righe da tabelle specificate nel formato CSV nella finestra di output per qualsiasi struttura tabelle. La speranza, lo script sarà utile per voi -
DECLARE
@TableName SYSNAME
, @ObjectID INT
DECLARE [tables] CURSOR READ_ONLY FAST_FORWARD LOCAL FOR
SELECT
'[' + s.name + '].[' + t.name + ']'
, t.[object_id]
FROM (
SELECT DISTINCT
t.[schema_id]
, t.[object_id]
, t.name
FROM sys.objects t WITH (NOWAIT)
JOIN sys.partitions p WITH (NOWAIT) ON p.[object_id] = t.[object_id]
WHERE p.[rows] > 0
AND t.[type] = 'U'
) t
JOIN sys.schemas s WITH (NOWAIT) ON t.[schema_id] = s.[schema_id]
WHERE t.name IN ('<your table name>')
OPEN [tables]
FETCH NEXT FROM [tables] INTO
@TableName
, @ObjectID
DECLARE
@SQLInsert NVARCHAR(MAX)
, @SQLColumns NVARCHAR(MAX)
, @SQLTinyColumns NVARCHAR(MAX)
WHILE @@FETCH_STATUS = 0 BEGIN
SELECT
@SQLInsert = ''
, @SQLColumns = ''
, @SQLTinyColumns = ''
;WITH cols AS
(
SELECT
c.name
, datetype = t.name
, c.column_id
FROM sys.columns c WITH (NOWAIT)
JOIN sys.types t WITH (NOWAIT) ON c.system_type_id = t.system_type_id AND c.user_type_id = t.user_type_id
WHERE c.[object_id] = @ObjectID
AND c.is_computed = 0
AND t.name NOT IN ('xml', 'geography', 'geometry', 'hierarchyid')
)
SELECT
@SQLTinyColumns = STUFF((
SELECT ', [' + c.name + ']'
FROM cols c
ORDER BY c.column_id
FOR XML PATH, TYPE, ROOT).value('.', 'NVARCHAR(MAX)'), 1, 2, '')
, @SQLColumns = STUFF((SELECT CHAR(13) +
CASE
WHEN c.datetype = 'uniqueidentifier'
THEN ' + '';'' + ISNULL('''' + CAST([' + c.name + '] AS VARCHAR(MAX)) + '''', ''NULL'')'
WHEN c.datetype IN ('nvarchar', 'varchar', 'nchar', 'char', 'varbinary', 'binary')
THEN ' + '';'' + ISNULL('''' + CAST(REPLACE([' + c.name + '], '''', '''''''') AS NVARCHAR(MAX)) + '''', ''NULL'')'
WHEN c.datetype = 'datetime'
THEN ' + '';'' + ISNULL('''' + CONVERT(VARCHAR, [' + c.name + '], 120) + '''', ''NULL'')'
ELSE
' + '';'' + ISNULL(CAST([' + c.name + '] AS NVARCHAR(MAX)), ''NULL'')'
END
FROM cols c
ORDER BY c.column_id
FOR XML PATH, TYPE, ROOT).value('.', 'NVARCHAR(MAX)'), 1, 10, 'CHAR(13) + '''' +')
DECLARE @SQL NVARCHAR(MAX) = '
SET NOCOUNT ON;
DECLARE
@SQL NVARCHAR(MAX) = ''''
, @x INT = 1
, @count INT = (SELECT COUNT(1) FROM ' + @TableName + ')
IF EXISTS(
SELECT 1
FROM tempdb.dbo.sysobjects
WHERE ID = OBJECT_ID(''tempdb..#import'')
)
DROP TABLE #import;
SELECT ' + @SQLTinyColumns + ', ''RowNumber'' = ROW_NUMBER() OVER (ORDER BY ' + @SQLTinyColumns + ')
INTO #import
FROM ' + @TableName + '
WHILE @x < @count BEGIN
SELECT @SQL = STUFF((
SELECT ' + @SQLColumns + ' + ''''' + '
FROM #import
WHERE RowNumber BETWEEN @x AND @x + 9
FOR XML PATH, TYPE, ROOT).value(''.'', ''NVARCHAR(MAX)''), 1, 1, '''')
PRINT(@SQL)
SELECT @x = @x + 10
END'
EXEC sys.sp_executesql @SQL
FETCH NEXT FROM [tables] INTO
@TableName
, @ObjectID
END
CLOSE [tables]
DEALLOCATE [tables]
Nella finestra di output si otterrà qualcosa di simile (AdventureWorks.Person.Person):
1;EM;0;NULL;Ken;J;Sánchez;NULL;0;92C4279F-1207-48A3-8448-4636514EB7E2;2003-02-08 00:00:00
2;EM;0;NULL;Terri;Lee;Duffy;NULL;1;D8763459-8AA8-47CC-AFF7-C9079AF79033;2002-02-24 00:00:00
3;EM;0;NULL;Roberto;NULL;Tamburello;NULL;0;E1A2555E-0828-434B-A33B-6F38136A37DE;2001-12-05 00:00:00
4;EM;0;NULL;Rob;NULL;Walters;NULL;0;F2D7CE06-38B3-4357-805B-F4B6B71C01FF;2001-12-29 00:00:00
5;EM;0;Ms.;Gail;A;Erickson;NULL;0;F3A3F6B4-AE3B-430C-A754-9F2231BA6FEF;2002-01-30 00:00:00
6;EM;0;Mr.;Jossef;H;Goldberg;NULL;0;0DEA28FD-EFFE-482A-AFD3-B7E8F199D56F;2002-02-17 00:00:00
trovato un legame veramente utile per questo . Utilizzando SQLCMD per questo è davvero più facile che risolvere questo con una stored procedure
http://www.excel-sql-server.com/sql-server-export-to-excel-using-bcp-sqlcmd-csv.htm
Penso che sia possibile utilizzare il comando bcp. Sono anche nuovo a questo comando, ma ho seguito this link e ha funzionato per me.
Ho anche usato BCP e ha trovato un paio di altri posti utili che potrebbero beneficiare gli altri se trovare questa discussione
Non utilizzare VARCHAR(MAX)
come @sql
o @cmd
variabile per xp_cmdshell; si otterrà ed errori
Msg 214, livello 16, stato 201, procedura xp_cmdshell, riga 1 Procedura si aspetta che il parametro 'command_string' di tipo 'varchar'.
http://www.sqlservercentral.com/Forums/Topic1071530-338-1.aspx
Usa NULLIF
per ottenere gli spazi per il file CSV, invece di un NUL
(visualizzabili in hex editor, o Notepad ++). Ho usato che nel SELECT
economico BCP
How to make Microsoft BCP export empty string instead of a NUL char?
è possibile seguire questi Per creare CSV da SQL seguire i passaggi indicati su questo sito
https://www.excel-sql-server.com/sql-server-export-to-excel-using-bcp-sqlcmd-csv.htm
E, utilizzare questo link per salvare in qualche luogo fisico.
https://www.codeproject.com/Questions/546777/HowplusToplusExportplusDataplusToplustheplus-csvpl
esiste un modo per consentire a SQL Server di aprire Windows Explorer per consentire all'utente di determinare il nome e il percorso di salvataggio del file? – tCoe
https://www.codeproject.com/Questions/546777/HowplusToplusExportplusDataplusToplustheplus-csvpl –
Giusto per rispondere a un modo nativo per fare questo che alla fine ha funzionato, tutto doveva essere colato come varchar
ALTER PROCEDURE [clickpay].[sp_GetDocuments]
@Submid bigint
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @raw_sql varchar(max)
DECLARE @columnHeader VARCHAR(max)
SELECT @columnHeader = COALESCE(@columnHeader+',' ,'')+ ''''+column_name +'''' FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'Documents'
DECLARE @ColumnList VARCHAR(max)
SELECT @ColumnList = COALESCE(@ColumnList+',' ,'')+ 'CAST('+column_name +' AS VARCHAR)' FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'Documents'
SELECT @raw_sql = 'SELECT '+ @columnHeader +' UNION ALL SELECT ' + @ColumnList + ' FROM ' + 'Documents where Submid = ' + CAST(@Submid AS VARCHAR)
-- Insert statements for procedure here
exec(@raw_sql)
FINE
Oltre alle risposte qui sotto, lo farei considera se vuoi veramente generare il file csv dalla procedura oppure no. Il primo problema sono le autorizzazioni: l'account del servizio SQL Server avrà bisogno dell'autorizzazione per scrivere in una cartella di output, il che potrebbe causare problemi. Il secondo problema è che in genere è meglio separare i dati dalla formattazione/presentazione. Lascia che la procedura generi i risultati, quindi usa uno script esterno per generare il file csv. In questo modo puoi fare molte cose diverse con i risultati della procedura, non è 'hardcoded' per generare un file csv. – Pondlife