如何用PowerShell动态生成SQL语句批量插入多列CSV数据?
动态生成INSERT语句批量导入CSV到SQL表
刚好遇到过类似的场景,我来给你一个不用硬编码列名的解决方案,完美适配不同列数的CSV和SQL表!
核心思路
我们需要动态获取CSV的列名,然后为每一行数据自动生成对应的INSERT语句,同时处理空值和SQL语法转义问题,彻底摆脱硬编码的麻烦。
第一步:可靠获取CSV列名
你之前用Split(",")的方式有个隐患——如果CSV列名里包含逗号(比如列名是"Name, Age"),拆分就会出错。更可靠的方式是用Import-Csv自带的属性获取列名:
$csvPath = "C:\Users\vivek.singh\Desktop\ALL_EMAILS.csv" $csv = Import-CSV $csvPath # 获取CSV的所有列名 $csvColumnNames = $csv[0].PSObject.Properties.Name
第二步:动态生成完整的INSERT语句
接下来我们遍历CSV的每一行,自动拼接列名和对应的值,同时处理空值和单引号转义:
# 配置你的SQL服务器和数据库信息 $server = "你的SQL服务器实例" $database = "目标数据库名" $table = "目标表名" # 生成INSERT语句的列部分(比如:(Column1, Column2, Column3)) $columnsPart = "($($csvColumnNames -join ', '))" # 遍历每一行CSV数据 $csv | ForEach-Object { # 处理每一列的值:转义单引号,空值替换为SQL的NULL $values = $csvColumnNames | ForEach-Object { $cellValue = $_.PSObject.Properties[$_].Value if ($null -eq $cellValue -or $cellValue -eq '') { # 空值用SQL的NULL表示 "NULL" } else { # 转义SQL中的单引号:把'替换成'' "'$($cellValue -replace "'", "''")'" } } # 生成VALUES部分(比如:('张三', '25', NULL)) $valuesPart = "($($values -join ', '))" # 拼接完整的INSERT语句 $insertQuery = "INSERT INTO $table $columnsPart VALUES $valuesPart" # 执行SQL插入 Invoke-Sqlcmd -Database $database -ServerInstance $server -Query $insertQuery }
更安全的参数化版本(推荐)
上面的字符串拼接方式虽然能解决问题,但存在SQL注入风险(比如某个CSV值是'); DROP TABLE Users;--)。用参数化查询可以彻底避免这个问题,同时不用手动转义单引号:
# 配置信息和获取列名部分和上面一致 $server = "你的SQL服务器实例" $database = "目标数据库名" $table = "目标表名" $csvPath = "C:\Users\vivek.singh\Desktop\ALL_EMAILS.csv" $csv = Import-CSV $csvPath $csvColumnNames = $csv[0].PSObject.Properties.Name $columnsPart = "($($csvColumnNames -join ', '))" $csv | ForEach-Object { # 构建参数哈希表,键是参数名(@列名),值是对应单元格的值 $sqlParams = @{} $placeholders = $csvColumnNames | ForEach-Object { $paramName = "@$_" $sqlParams[$paramName] = $_.PSObject.Properties[$_].Value $paramName } # 生成带参数占位符的VALUES部分 $valuesPart = "($($placeholders -join ', '))" $insertQuery = "INSERT INTO $table $columnsPart VALUES $valuesPart" # 用参数化方式执行SQL Invoke-Sqlcmd -Database $database -ServerInstance $server -Query $insertQuery -Parameter $sqlParams }
处理多个CSV和多个表
如果要批量处理多个CSV对应多个SQL表,可以把逻辑封装成函数,循环处理:
function Import-CsvToSql { param( [string]$ServerInstance, [string]$Database, [string]$TableName, [string]$CsvPath ) $csv = Import-CSV $CsvPath $csvColumnNames = $csv[0].PSObject.Properties.Name $columnsPart = "($($csvColumnNames -join ', '))" $csv | ForEach-Object { $sqlParams = @{} $placeholders = $csvColumnNames | ForEach-Object { $paramName = "@$_" $sqlParams[$paramName] = $_.PSObject.Properties[$_].Value $paramName } $valuesPart = "($($placeholders -join ', '))" $insertQuery = "INSERT INTO $TableName $columnsPart VALUES $valuesPart" Invoke-Sqlcmd -Database $Database -ServerInstance $ServerInstance -Query $insertQuery -Parameter $sqlParams } } # 批量调用示例 $importTasks = @( @{ ServerInstance = "你的服务器"; Database = "DB1"; TableName = "Table1"; CsvPath = "C:\csv1.csv" }, @{ ServerInstance = "你的服务器"; Database = "DB1"; TableName = "Table2"; CsvPath = "C:\csv2.csv" } ) $importTasks | ForEach-Object { Import-CsvToSql @_ }
内容的提问来源于stack exchange,提问作者Vivek Kumar Singh
相关产品推荐
相关产品推荐

