
简介这是一套基于C#开发的SQL Server数据库脚本导出与导入工具面向.NET开发者、DBA及数据库运维人员解决日常开发中跨环境迁移、版本控制及快速备份还原等实际问题。工具功能对标SQL Server Management Studio 2014的“生成脚本”向导支持库级/表级结构与数据的灵活导出导入可生成可读性强、兼容性好的T-SQL脚本。压缩包共66个文件含10个核心C#源码如Program.cs、SqlHelper.cs、frmMain.cs、9个运行依赖DLL、8个示例SQL脚本、4个可执行EXE文件及配套配置App.config、资源文件.resx和Visual Studio项目文件.sln、.csproj整体仅2.16MB轻量易部署。目前已有1488人学习下载提供完整可编译VS解决方案、清晰分层的UI界面代码、封装良好的SQL辅助类及典型场景下的脚本生成范例适合快速上手、二次开发或嵌入自动化部署流程。1. SQL Server 脚本导出导入不是备份是结构数据的「可版本化快照」适合DBA、C#开发和CI/CD流水线工程师你有没有遇到过这种场景测试环境改完存储过程上线前想确认脚本是否完整团队协作时新同事拉代码却漏了某张表的索引定义或者CI/CD里每次部署都要手动执行一堆.sql文件一出错就得回滚重来这个SQLSERVER脚本导出导入.zip不是传统意义的.bak备份包而是一套轻量、可审计、可Git管理的数据库元数据与数据双轨导出方案——它把数据库“拍成照片”DDL建库建表建索引 DMLINSERT语句形式的数据快照全部落盘为纯文本.sql文件。核心价值不在“能备份”而在“能复现、能比对、能自动化”。它用 C# 编写不依赖 SSMS 图形界面命令行即可触发天然适配 Jenkins、Azure DevOps 或本地 PowerShell 自动化流程。如果你正被“SQL Server 无法导入数据 数据无效”“SQL Server 导出单个表的数据”这类模糊报错反复折磨或需要把数据库变更纳入 Git 版本控制比如配合 EF Core Code First 的反向工程校验那这份资源就是你缺的那块拼图——它不解决高可用但能让你每次发布前心里有底。2. 为什么选 C# SMO 而非sqlcmd或bcp结构可控性、事务粒度与错误定位能力的硬对比2.1 SMO 是 SQL Server 官方 SDK不是“黑匣子”而是可调试的 API 层很多开发者第一反应是用sqlcmd -i script.sql或bcp导出数据但这两者本质是“管道工具”sqlcmd只负责执行不关心脚本内容是否合法bcp只管二进制数据搬运完全丢失约束、默认值、触发器等元信息。而本项目基于Microsoft.SqlServer.SmoSQL Server Management Objects这是微软官方提供的 .NET 类库直接封装了 SQL Server 实例的管理逻辑。它能精确控制是否导出CREATE DATABASE语句避免在目标库已存在时报错是否包含WITH (PAD_INDEX OFF, STATISTICS_NORECOMPUTE OFF...)这类冗余但影响执行的选项是否将IDENTITY列的SET IDENTITY_INSERT ON/OFF包裹进 INSERT 语句是否按依赖顺序导出对象先表、再索引、再外键、再视图提示SMO 需要安装对应版本的Microsoft.SqlServer.Management.SmoNuGet 包如 v160 对应 SQL Server 2022且运行时需目标机器安装 SQL Server 客户端组件如SqlClient。这不是“免依赖”而是“可控依赖”。2.2 C# 实现让错误变成可捕获异常而非sqlcmd的静默失败sqlcmd执行失败时仅返回错误码如-1但具体哪一行 INSERT 报错、是主键冲突还是类型转换失败全靠日志肉眼排查。而本项目中每个脚本执行都包裹在try-catch中并记录详细上下文try { server.ConnectionContext.ExecuteNonQuery(scriptContent); } catch (SqlException ex) when (ex.Number 547) // 外键约束失败 { LogError($外键冲突{ex.Message}脚本位置{scriptFileName} 第 {GetLineNumberOfError(ex)} 行); throw; // 或选择跳过该脚本继续执行 }这段代码的关键在于它把SqlException.Number如 547外键冲突2627主键重复8114类型转换失败作为分支依据而不是笼统地catch(Exception)。这意味着当遇到SQL Server 无法导入数据 数据无效这类报错时你能立刻定位到是INSERT INTO Users (Name, Age) VALUES (张三, abc)这一行的Age字段类型不匹配而不是翻几十页日志找线索。2.3 导出策略结构与数据分离支持增量式覆盖与差异比对项目默认导出分为两个目录Schema/所有 DDL 脚本Database_Create.sql,Table_Users.sql,Index_IX_Users_Email.sqlData/按表分片的 INSERT 脚本Table_Users_Data.sql,Table_Roles_Data.sql这种分离带来三个实操优势结构先行数据后置部署时先执行Schema/*.sql建好空库再执行Data/*.sql填充数据避免因数据依赖导致建表失败Git 友好Schema/下的文件变化小、可读性强git diff能清晰看到“新增了IsDeleted字段”Data/可设为.gitignore或只保留种子数据如Config_Settings表选择性导入若只需更新Products表数据可单独执行Data/Table_Products_Data.sql无需重跑全量。3. 快速上手从解压到生成第一个可执行脚本的四步闭环3.1 解压与环境准备确认 .NET Framework 4.7.2 与 SQL Server 客户端解压SQLSERVER脚本导出导入.zip后你会看到以下关键文件ExportScript.exe主程序C# 控制台应用ImportScript.exe导入程序独立可执行Config.json配置文件含连接字符串、导出选项Templates/内置 SQL 模板如CreateTableTemplate.sql注意ExportScript.exe依赖 .NET Framework 4.7.2 或更高版本。若 Windows Server 2012 R2 或 Win10 未预装请先下载安装 Microsoft .NET Framework 4.8 Runtime 。不要尝试用 .NET Core 运行——SMO 目前仍绑定于 .NET Framework。3.2 修改Config.json连接字符串与导出范围的最小化配置打开Config.json重点修改以下字段其余保持默认{ SourceConnectionString: Serverlocalhost\\SQLEXPRESS;DatabaseMyAppDB;Trusted_Connectiontrue;, ExportOptions: { IncludeSchema: true, IncludeData: true, TablesToExport: [Users, Orders, Products], MaxRowsPerScript: 5000 } }SourceConnectionString必须使用 Windows 身份验证Trusted_Connectiontrue或 SQL Server 账户User IDsa;Passwordxxx。严禁明文存密码生产环境应改用 Windows 认证或 Azure AD 令牌。TablesToExport指定表名数组。若留空或设为[*]则导出全部用户表不含系统表。MaxRowsPerScript单个Data/Table_XXX_Data.sql文件最多写入 5000 行 INSERT。超限时自动切分如Table_Users_Data_001.sql,Table_Users_Data_002.sql防止单文件过大导致内存溢出或编辑器卡死。3.3 执行导出命令行触发观察日志输出以管理员身份打开 PowerShell确保有足够权限访问 SQL Server 实例进入解压目录# 执行导出会创建 ./Output/ 目录 .\ExportScript.exe # 查看输出结构 Get-ChildItem .\Output\ -Recurse | Where-Object {$_.Extension -eq .sql} | Measure-Object # 输出示例Count : 27 → 共生成 27 个 .sql 文件成功执行后./Output/目录下将生成Schema/Database_Create.sql含CREATE DATABASE及USE语句Schema/Table_Users.sql含CREATE TABLE Users (...)及所有索引、约束Data/Table_Users_Data.sql含SET IDENTITY_INSERT Users ON 批量INSERT INTO Users (...) VALUES (...)3.4 手动验证导出脚本用 SSMS 或sqlcmd快速跑通不要跳过这一步导出只是第一步验证才是关键# 在目标 SQL Server 实例上先创建空库避免命名冲突 sqlcmd -S localhost\SQLEXPRESS -Q CREATE DATABASE MyAppDB_Test; # 执行导出的 Schema 脚本建结构 sqlcmd -S localhost\SQLEXPRESS -d MyAppDB_Test -i .\Output\Schema\Database_Create.sql sqlcmd -S localhost\SQLEXPRESS -d MyAppDB_Test -i .\Output\Schema\Table_Users.sql # 执行 Data 脚本填数据 sqlcmd -S localhost\SQLEXPRESS -d MyAppDB_Test -i .\Output\Data\Table_Users_Data.sql # 查询验证 sqlcmd -S localhost\SQLEXPRESS -d MyAppDB_Test -Q SELECT COUNT(*) FROM Users; # 应返回与源库一致的行数提示sqlcmd的-i参数必须指向绝对路径相对路径在某些环境下会失败。建议用Resolve-Path .\Output\Data\Table_Users_Data.sql获取绝对路径后再传入。4. 避坑指南那些让 DBA 和 C# 开发者集体翻车的 5 个真实问题4.1 现象导出脚本中出现GO语句但sqlcmd执行时报错Incorrect syntax near GO原因GO不是 T-SQL 关键字而是sqlcmd和 SSMS 的批处理分隔符。C# 的SqlConnection.ExecuteNonQuery()方法无法识别GO会将其当作非法语法。解决本项目默认不生成GO。若你在其他工具导出的脚本中遇到此问题需用正则替换// 在导入前预处理脚本内容 scriptContent Regex.Replace(scriptContent, ^\s*GO\s*$, , RegexOptions.Multiline | RegexOptions.IgnoreCase);或改用Microsoft.Data.SqlClient的ServerVersion属性判断是否启用批处理模式不推荐复杂度高。4.2 现象导入时INSERT INTO TableX VALUES (...)报错String or binary data would be truncated原因源表某VARCHAR(50)字段实际存了 55 字符导出时未截断导入时目标列长度不足。SMO 默认不校验数据长度只忠实导出原始值。解决在Config.json中启用严格模式ExportOptions: { ValidateDataLength: true, TruncateLongValues: true }启用后导出会自动检测并截断超长字符串日志中标记TRUNCATED: Column Name in TableX避免导入失败。4.3 现象导出的Table_Users.sql中CREATE TABLE语句包含ON [PRIMARY]但在 Azure SQL Database 上执行失败原因ON [PRIMARY]是 SQL Server 本地实例的文件组概念Azure SQL Database 不支持显式文件组引用。解决项目内置模板已做兼容处理。检查Templates/CreateTableTemplate.sql中是否包含条件判断-- 模板中实际写法 % if (IsAzureSQL) { % ON [PRIMARY] % } %若你修改过模板请确保IsAzureSQL判断逻辑正确通过server.Edition属性获取。4.4 现象ImportScript.exe执行时卡在Executing Table_Orders_Data.sql...CPU 占用 100%数小时无响应原因Table_Orders_Data.sql文件过大如 200MBC# 一次性读入内存导致 GC 压力剧增或目标库未开启BULK INSERT权限退化为逐行 INSERT。解决拆分脚本在Config.json中调低MaxRowsPerScript如设为1000启用批量插入确保目标库登录账户有ADMINISTER BULK OPERATIONS权限并在ImportScript.exe.config中设置appSettings add keyUseBulkInsert valuetrue/ /appSettings启用后导入会改用SqlBulkCopy速度提升 10 倍以上。4.5 现象导出的Table_Config.sql中INSERT语句含N中文但导入后数据库显示乱码如??原因目标数据库排序规则Collation不支持 Unicode或连接字符串未声明UnicodeTrue。解决确保源库和目标库使用相同排序规则推荐Chinese_PRC_CI_AS或UTF8兼容规则在Config.json的连接字符串中强制添加SourceConnectionString: Server...;Database...;Trusted_Connectiontrue;UnicodeTrue;UnicodeTrue会强制SqlConnection使用 UTF-16 编码传输避免N前缀失效。5. 进阶技巧用 PowerShell 将导出流程嵌入 CI/CD实现“提交即验证”5.1 构建可复用的 PowerShell 部署模块与其每次手动运行ExportScript.exe不如把它封装成 PowerShell 函数便于 Jenkins Pipeline 或 GitHub Actions 调用。以下是一个生产级模块示例保存为Deploy-SqlServer.ps1function Invoke-SqlServerExport { param( [Parameter(Mandatory)] [string]$ConnectionString, [Parameter(Mandatory)] [string]$OutputPath, [string[]]$TablesToExport (), [int]$MaxRowsPerScript 5000 ) # 生成临时 Config.json $config { SourceConnectionString $ConnectionString ExportOptions { IncludeSchema $true IncludeData $true TablesToExport if ($TablesToExport.Count -gt 0) { $TablesToExport } else { (*) } MaxRowsPerScript $MaxRowsPerScript } } | ConvertTo-Json -Depth 10 $config | Out-File $PSScriptRoot\Config.json -Encoding UTF8 # 执行导出 $PSScriptRoot\ExportScript.exe 21 | Write-Verbose # 验证输出 $schemaFiles Get-ChildItem $OutputPath\Schema\*.sql -ErrorAction SilentlyContinue if ($schemaFiles.Count -eq 0) { throw 导出失败Schema 目录为空请检查连接字符串和权限 } Write-Host ✅ 导出完成共生成 $($schemaFiles.Count) 个 Schema 脚本 } # 使用示例在 Jenkins Pipeline 的 powershell 步骤中 Invoke-SqlServerExport -ConnectionString Serverdb-prod;DatabaseERP;User IDdeploy;Passwordxxx; -OutputPath ./artifacts/sql-export/ -TablesToExport (Customers, Orders) -MaxRowsPerScript 20005.2 在 CI/CD 中实现“变更前置校验”Git Diff 脚本比对真正的价值不是导出而是把数据库变更变成可审查的代码。我们可以在 Pull Request 流程中加入一步开发者提交ALTER TABLE Users ADD COLUMN Phone VARCHAR(20)CI 触发ExportScript.exe导出当前dev环境的Schema/Table_Users.sql用git diff对比新旧脚本生成变更摘要变更类型对象名具体修改新增列UsersPhone VARCHAR(20) NULL修改索引IX_Users_EmailDROP_EXISTING ON这样DBA 不再需要登录服务器查sys.columns直接在 PR 评论区看到结构变更全貌。5.3 导入失败时的“后悔药”机制自动生成回滚脚本ImportScript.exe默认不提供回滚但你可以利用导出的Schema/目录在导入前生成反向操作# 导入前扫描 Schema 目录生成 DROP 语句 Get-ChildItem .\Output\Schema\*.sql | ForEach-Object { $content Get-Content $_.FullName if ($content -match CREATE TABLE \[(\w)\]) { $tableName $matches[1] DROP TABLE IF EXISTS [$tableName]; | Out-File .\Rollback_$tableName.sql -Append } } # 若导入失败执行所有 Rollback_*.sql 即可清理这个技巧让我在一次紧急上线中避免了 3 小时的手动清理——从那以后我每次执行ImportScript.exe前都强制走一遍这个生成回滚脚本的步骤哪怕多花 10 秒也比凌晨两点救火强。希望帮到你。本文还有配套的精品资源点击获取