【问题标题】:Stored procedure that exports data into csv files only exports to one file将数据导出到csv文件的存储过程只导出到一个文件
【发布时间】:2012-06-14 18:37:56
【问题描述】:

我有一个有趣的脚本:

DECLARE @StartDT DATE
DECLARE @MinDOS DATE
DECLARE @TableName VARCHAR(50)
SET @TableName = 'ViewAccountDetail'
SELECT @MinDOS = MIN(dos) FROM accn_demographics
SELECT @StartDT = 
    CAST(CAST(datepart(YYYY,@MinDOS) AS varchar) + '-' + CAST(datepart(mm,@MinDOS) AS varchar) + '-' + CAST('01' AS varchar) AS DATETIME)
DECLARE @FileLocation VARCHAR(50)

WHILE @StartDT < '20110901'
BEGIN
    SET @FileLocation='C:\test\'+@TableName+cast(@StartDT as varchar)+'.csv'
    EXEC BCP_Text_File @TableName, @FileLocation    
    SET @StartDT = DATEADD(MONTH,1,@StartDT)
END

应该做的是将数据导出到 csv 文件中。文件名应为:

C:\test\ViewAccountDetail2011-01-01.csv
C:\test\ViewAccountDetail2011-02-01.csv
C:\test\ViewAccountDetail2011-03-01.csv
C:\test\ViewAccountDetail2011-04-01.csv
C:\test\ViewAccountDetail2011-05-01.csv
C:\test\ViewAccountDetail2011-06-01.csv
C:\test\ViewAccountDetail2011-07-01.csv
C:\test\ViewAccountDetail2011-08-01.csv

但它将所有数据存储到同一个:

C:\test\ViewAccountDetail2011-01-01.csv

我做了一个print @FileLocation 并确认它正确地更新了这个变量。

我在这里遗漏了什么明显的、明显的东西吗?

仅供参考:

EXEC BCP_Text_File @TableName, @FileLocation

调用这个过程:

  ALTER PROCEDURE [dbo].[BCP_Text_File]
    @table    NVARCHAR(255),  
    @filename VARCHAR(100)  
AS
BEGIN
  SET NOCOUNT ON;

  IF OBJECT_ID(@table) IS NOT NULL
  BEGIN
    DECLARE 
        @sql NVARCHAR(MAX), 
        @cols NVARCHAR(MAX) = N'';

    SELECT @cols += ',' + name
      FROM sys.columns
      WHERE [object_id] = OBJECT_ID(@table)
      ORDER BY column_id;

    SELECT @cols = STUFF(@cols, 1, 1, '');

    SET @sql = N'EXEC master..xp_cmdshell ''bcp "SELECT ''''' 
        + REPLACE(@cols, ',', ''''',''''') + ''''' UNION ALL SELECT ' 
        + 'RTRIM(' + REPLACE(@cols, ',', '),RTRIM(') + ') FROM ' 
        + DB_NAME() + '..' + @table + '" queryout "' + @filename + '" -c -T''';  

    EXEC sp_executesql @sql;
  END
  ELSE
  BEGIN
    SELECT 'The table '+@table+' does not exist in the database';
  END
END

GO

非常感谢您的帮助和指导!!

【问题讨论】:

  • 将此行改写为SET @FileLocation='C:\test\'+@TableName+convert(varchar(20),@StartDT)+'.csv'
  • 尝试将您的代码减少到真正触及问题核心的几行代码,并且不需要对外部过程进行任何调用。然后我们可以尝试自己运行代码。如果我要调试它,我想要一些我可以复制+粘贴到 SSMS 中并运行而不会出现任何错误、丢失表、丢失存储过程等的东西。换句话说,让它成为一个简单、独立的示例,可以重现您的错误。
  • 也试试改这个SET @StartDT = DATEADD(month,1,@StartDT)
  • 我有一个答案,并且每次我尝试发布它时都会出错......这段代码对我有用。日期的东西很好用@CoDeaDDict,并且文件都是用相同的数据创建的(表的全部内容发送到存储过程中)。您确定您正在运行您提供的代码吗?
  • 当我用 "SELECT @MinDOS = '20110101'" 代替 "MIN(dos) FROM accn_demographics" 时,我得到了想要的结果,所以您可以先查看 accn_demographics 返回的值。

标签: sql sql-server sql-server-2008 tsql stored-procedures


【解决方案1】:

对我来说似乎工作得很好。我有几个建议:

(1) 停止所有字符串连接来构建日期。您可以更轻松地完成相同的操作:

SELECT @StartDT = DATEADD(MONTH, DATEDIFF(MONTH, '19000101', @MinDOS), '19000101');

(2)stop declaring varchar without length。为了确保正确的输出,我更喜欢转换:

SET @FileLocation = 'C:\test\' + @TableName
   + CONVERT(CHAR(10), @StartDT, 120) + '.csv';

(3) 与其通过运行存储过程并检查文件夹中的输出来“调试”代码,不如先对输入进行健全性检查?另外,为什么要使用两个变量来表示日期?

DECLARE 
   @StartDT DATE, 
   @TableName NVARCHAR(50), 
   @FileLocation VARCHAR(255);

SET @TableName = N'ViewAccountDetail';

SELECT @StartDT = DATEADD(MONTH, DATEDIFF(MONTH, '19000101', MIN(dos)), '19000101')
   FROM dbo.accn_demographics;

   PRINT @StartDT;
-- ^^^^^ debugging 101 - what month do we think we're starting at?

WHILE @StartDT < '20110901'
BEGIN
    SET @FileLocation = 'C:\test\' + @TableName
      + CONVERT(CHAR(10), @StartDT, 120) + '.csv';

      PRINT @FileLocation;
    --^^^^^ again, debugging 101 - what does the filename currently look like?

    --EXEC BCP_Text_File @TableName, @FileLocation    
    SET @StartDT = DATEADD(MONTH, 1, @StartDT);
END

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-16
    • 2014-08-07
    • 2014-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多