如何通过PowerShell修改Always Encrypted列中的数据(AKV场景)
解决方案:PowerShell操作带Always Encrypted(AKV存储主密钥)的SQL Server插入/更新
核心问题分析
你遇到的Invalid key store provider name: 'AZURE_KEY_VAULT'错误,本质是未注册Azure Key Vault的密钥存储提供器——该提供器不属于SQL Client默认的系统提供器,需要手动加载专用包并注册后才能使用。
以下提供两种可行的实现方案:
方案一:直接使用Microsoft.Data.SqlClient(推荐)
通过手动加载AKV提供器、注册令牌回调,实现参数化的插入/更新操作。
步骤1:安装必要的NuGet包
首次运行需安装以下包:
# 安装Microsoft.Data.SqlClient及AKV扩展包 Install-Package Microsoft.Data.SqlClient -Scope CurrentUser Install-Package Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider -Scope CurrentUser
步骤2:加载程序集并注册AKV提供器
# 加载已安装的程序集 $sqlClientAssembly = (Get-Package Microsoft.Data.SqlClient).Source $akvProviderAssembly = (Get-Package Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider).Source Add-Type -Path $sqlClientAssembly Add-Type -Path $akvProviderAssembly # 连接Azure并获取AKV访问令牌 Import-Module Az.Accounts -MinimumVersion 2.2.0 Connect-AzAccount $akvToken = (Get-AzAccessToken -ResourceUrl https://vault.azure.net).Token # 创建AKV提供器实例,配置令牌自动获取回调 $akvKeyStoreProvider = New-Object Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.AzureKeyVaultKeyStoreProvider( [Func[string, string]] { return $akvToken } ) # 注册提供器到SqlClient全局配置 [Microsoft.Data.SqlClient.SqlConnection]::RegisterColumnEncryptionKeyStoreProvider( [Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.AzureKeyVaultKeyStoreProvider]::ProviderName, $akvKeyStoreProvider )
步骤3:执行参数化插入/更新
# 构建连接字符串(需包含Column Encryption Setting=Enabled) $connectionString = "Data Source=MYSERVER;Initial Catalog=MyDatabase;Integrated Security=True;Column Encryption Setting=Enabled;TrustServerCertificate=True" # 初始化连接和命令 $connection = New-Object Microsoft.Data.SqlClient.SqlConnection($connectionString) $connection.Open() # 定义插入查询 $query = "INSERT INTO [dbo].[table] ([val1],[val2],[val3]) VALUES (@a, @b, @c)" $command = New-Object Microsoft.Data.SqlClient.SqlCommand($query, $connection) # 添加带强制列加密的参数 $paramA = New-Object Microsoft.Data.SqlClient.SqlParameter("@a", [System.Data.DbType]::AnsiStringFixedLength) $paramA.Size = 4 $paramA.Value = "test" $paramA.ForceColumnEncryption = $true $command.Parameters.Add($paramA) | Out-Null $paramB = New-Object Microsoft.Data.SqlClient.SqlParameter("@b", [System.Data.DbType]::AnsiStringFixedLength) $paramB.Size = 8 $paramB.Value = "testval2" $paramB.ForceColumnEncryption = $true $command.Parameters.Add($paramB) | Out-Null $paramC = New-Object Microsoft.Data.SqlClient.SqlParameter("@c", [System.Data.DbType]::AnsiStringFixedLength) $paramC.Size = 8 $paramC.Value = "testval3" $paramC.ForceColumnEncryption = $true $command.Parameters.Add($paramC) | Out-Null # 执行命令并输出结果 $rowsAffected = $command.ExecuteNonQuery() Write-Host "操作成功,影响行数:$rowsAffected" # 清理资源 $connection.Close() $connection.Dispose()
方案二:结合dbatools实现
dbatools底层依赖Microsoft.Data.SqlClient,因此只需先完成AKV提供器的注册,再执行原有的dbatools代码即可:
# 先执行方案一中的【步骤1】和【步骤2】(加载程序集、注册AKV提供器) # 连接SQL实例并执行参数化查询 $server = Connect-DbaInstance -SqlInstance 'myserver' -Database 'mydb' -AlwaysEncrypted -TrustServerCertificate $params = @{ a = New-DbaSqlParameter -Direction Input -ParameterName "@a" -DbType AnsiStringFixedLength -Size 4 -SqlValue "test" -ForceColumnEncryption b = New-DbaSqlParameter -Direction Input -ParameterName "@b" -DbType AnsiStringFixedLength -Size 8 -SqlValue "testval2" -ForceColumnEncryption c = New-DbaSqlParameter -Direction Input -ParameterName "@c" -DbType AnsiStringFixedLength -Size 8 -SqlValue "testval3" -ForceColumnEncryption } Invoke-DbaQuery -SqlInstance $server -Query 'insert into [dbo].[table] ([val1],[val2],[val3]) values (@a, @b, @c)' -SqlParameter $params
关键注意事项
- AKV权限:运行PowerShell的账号需拥有AKV的
Get、WrapKey、UnwrapKey权限,否则无法访问密钥进行加密/解密。 - 令牌有效期:Azure访问令牌有效期约1小时,若脚本运行时间较长,需在令牌过期前重新获取并更新提供器的回调逻辑。
- 版本一致性:确保安装的NuGet包版本与你的.NET Web应用中使用的版本一致,避免兼容性问题。
内容的提问来源于stack exchange,提问作者Mazak
相关产品推荐
相关产品推荐

