首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

SQL Server BCP 二進制文件導入導出存儲過程:image/text/ntext 大字段處理

     編輯:MySQL 綜合教學

⚠️ 重要提示

本文內容為 **SQL Server (T-SQL) 存儲過程**,使用 `bcp` 工具與 `xp_cmdshell` 實現二進制大對象 (BLOB) 導入導出,**非 MySQL 技術**。MySQL 對應功能請使用 `SELECT ... INTO OUTFILE` / `LOAD DATA INFILE` 或應用層流式處理。

存儲過程完整代碼

CREATE PROCEDURE dbo.p_binaryIO
    @servename VARCHAR(30),   -- 服務器名稱
    @username  VARCHAR(30),   -- 用戶名
    @password  VARCHAR(30),   -- 密碼
    @tbname    VARCHAR(500),  -- 數據庫..表名 (如 db..tbl)
    @fdname    VARCHAR(30),   -- 目標字段名 (image/text/ntext)
    @fname     VARCHAR(1000), -- 文件完整路徑 (導出目標/導入源)
    @tj        VARCHAR(1000) = '', -- WHERE 條件 (導入時含字段需加表前綴)
    @isout     BIT = 1        -- 1=導出 (默認), 0=導入
AS
BEGIN
    SET NOCOUNT ON;
    
    DECLARE @fname_in VARCHAR(1000),  -- bcp 格式文件
            @fsize  VARCHAR(20),      -- 文件大小
            @m_tbname VARCHAR(50),    -- 臨時表名
            @sql VARCHAR(8000);
    
    -- 1. 獲取導入文件大小 (導入模式)
    IF @isout = 0 BEGIN
        CREATE TABLE #tb (
            [可選名] VARCHAR(20), [大小] INT,
            [創建日期] VARCHAR(10), [創建時間] VARCHAR(20),
            [上次寫操作日期] VARCHAR(10), [上次寫操作時間] VARCHAR(20),
            [上次訪問日期] VARCHAR(10), [上次訪問時間] VARCHAR(20), [特性] INT
        );
        INSERT INTO #tb EXEC master..xp_getfiledetails @fname;
        SELECT @fsize = [大小] FROM #tb;
        DROP TABLE #tb;
        IF @fsize IS NULL BEGIN
            PRINT '文件未找到'; RETURN;
        END
    END ELSE SET @fsize = '0';
    
    -- 2. 生成 bcp 格式文件 (描述字段結構)
    SET @m_tbname = '[##temp' + CAST(NEWID() AS VARCHAR(40)) + ']';
    SET @sql = 'SELECT * INTO ' + @m_tbname + ' FROM (
        SELECT NULL AS 類型
        UNION ALL SELECT 0 AS 前綴
        UNION ALL SELECT ' + @fsize + ' AS 長度
        UNION ALL SELECT NULL AS 結束
        UNION ALL SELECT NULL AS 格式
    ) a';
    EXEC(@sql);
    
    SET @fname_in = @fname + '_temp';
    SET @sql = 'bcp "' + @m_tbname + '" out "' + @fname_in + '" /S"' + @servename + '"'
        + CASE WHEN ISNULL(@username,'')='' THEN '' ELSE ' /U"' + @username + '"' END
        + ' /P"' + ISNULL(@password,'') + '" /c';
    EXEC master..xp_cmdshell @sql;
    
    DROP TABLE @m_tbname;  -- 清理臨時表
    
    -- 3. 執行導出或導入
    IF @isout = 1 BEGIN
        -- 導出: 查詢單行字段內容導出至文件
        SET @sql = 'bcp "SELECT TOP 1 ' + @fdname + ' FROM ' + @tbname 
            + CASE WHEN ISNULL(@tj,'')='' THEN '' ELSE ' WHERE ' + @tj END
            + '" QUERYOUT "' + @fname + '" /S"' + @servename + '"'
            + CASE WHEN ISNULL(@username,'')='' THEN '' ELSE ' /U"' + @username + '"' END
            + ' /P"' + ISNULL(@password,'') + '" /i"' + @fname_in + '"';
        EXEC master..xp_cmdshell @sql;
    END ELSE BEGIN
        -- 導入: 建立臨時表 -> bcp in -> 更新目標表
        SET @sql = 'SELECT TOP 0 ' + @fdname + ' INTO ' + @m_tbname + ' FROM ' + @tbname;
        EXEC(@sql);
        
        SET @sql = 'bcp "' + @m_tbname + '" IN "' + @fname + '" /S"' + @servename + '"'
            + CASE WHEN ISNULL(@username,'')='' THEN '' ELSE ' /U"' + @username + '"' END
            + ' /P"' + ISNULL(@password,'') + '" /i"' + @fname_in + '"';
        EXEC master..xp_cmdshell @sql;
        
        SET @sql = 'UPDATE ' + @tbname + ' SET ' + @fdname + ' = b.' + @fdname
            + ' FROM ' + @tbname + ' a, ' + @m_tbname + ' b'
            + CASE WHEN ISNULL(@tj,'')='' THEN '' ELSE ' WHERE ' + @tj END;
        EXEC(@sql);
        
        DROP TABLE @m_tbname;
    END
    
    -- 4. 清理格式文件
    SET @sql = 'DEL ' + @fname_in;
    EXEC master..xp_cmdshell @sql;
END;
GO

調用示例

-- 導出: 將 db..tb 表中符合條件的 img 字段導出到文件
EXEC p_binaryIO 'SERVER1', 'sa', 'pwd', 'mydb..mytable', 'img', 'C:\export\img.dat', 'id=100', 1;

-- 導入: 將文件導入到符合條件的行 (覆蓋模式)
EXEC p_binaryIO 'SERVER1', 'sa', 'pwd', 'mydb..mytable', 'img', 'C:\import\img.dat', 'id=100', 0;

核心機制解析

組件作用
bcp (Bulk Copy Program)SQL Server 命令行批量複製工具,高性能數據移動
xp_cmdshell擴展存儲過程,在 SQL Server 進程內執行 OS 命令 (需啟用)
格式文件 (.fmt / 此處為臨時表生成)描述數據文件結構:字段類型、長度、終止符、前綴長度等
`image` / `text` / `ntext`SQL Server 舊版大字段類型 (已棄用,現用 `varbinary(max)`/`varchar(max)`/`nvarchar(max)`)

前置條件與權限

  1. 啟用 `xp_cmdshell`:`EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;`
  2. 服務帳號需有文件系統讀寫權限 (導出目錄寫、導入文件讀)
  3. `bcp` 在 PATH 中或使用完整路徑
  4. 導入時 `@tj` 條件若包含目標字段名,需加表別名前綴

MySQL 對應方案對比

場景SQL Server (BCP)MySQL
導出 BLOB 到文件`bcp QUERYOUT` + 格式文件`SELECT blob_col INTO DUMPFILE '/path/file' FROM t WHERE id=1;` (單行單文件)
批量導出同上應用層分批 `SELECT` 寫文件、或 `mysqldump --tab` (僅文本)
導入文件到 BLOB`bcp IN` + 臨時表 UPDATE`LOAD_FILE('/path/file')` 在 INSERT/UPDATE 中使用 (需 `secure_file_priv`、文件大小限制)
大文件流式處理BCP 原生流式應用層分片寫入、或 UDF (如文中 176693/176694)

現代化建議

  • SQL Server 2008+ 建議使用 `varbinary(max)` + `FILESTREAM` / `FileTable` 替代 `image`,支援流式訪問、NTFS 緩存、備份整合。
  • 避免在存儲過程中使用 `xp_cmdshell` (安全風險、難調試、跨平台差),改用 **SSIS、PowerShell、應用層 (C#/Python)、PolyBase** 進行 ETL。
  • MySQL 8.0+ 推薦應用層處理大對象,或使用 `LOAD DATA INFILE` (文本) 配合 `JSON`/`BLOB` 字段應用層分片。

總結

此存儲過程展示了 SQL Server 早期處理 BLOB 導入導出的經典模式:**bcp + 格式文件 + xp_cmdshell + 臨時表中轉**。雖能工作,但屬於**舊技術棧**,現代架構應遷移至更安全、可維護、跨平台的方案。MySQL 用戶請參考應用層流式處理或 UDF 方案 (文章 176693/176694)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved