web-dev-qa-db-ja.com

Always Encryptedで暗号化された列を持つテーブルにデータを一括挿入することはできますか?

SSMSでは、csvファイルから、SQL Server 2016のAlways Encrypted機能を使用して列が暗号化されているテーブルに一括挿入しようとしています。

これは私たちが使用しているコマンドです:

INSERT INTO membersE
SELECT *
FROM OPENROWSET(
    BULK 'c:\members.csv', 
    FORMATFILE = 'c:\membersEFormat.xml',
    FIRSTROW = 2
    ) m

これは、暗号化された列に挿入しようとしたときに発生する一般的なエラーを返します。

メッセージ206、レベル16、状態2、行6
【.____。]オペランドタイプ衝突:VARBINARYを使用して暗号化VARCHAR(50)との互換性がない(encryption_type = 'DETERMINISTIC'、encryption_algorithm_name = 'AEAD_AES_256_CBC_HMAC_SHA_256'、column_encryption_key_name = 'CEK_Auto1'、column_encryption_key_database_name = 'DATABASE')COLLATION_NAME = 'Latin1_General_BIN2'

SSMS経由で暗号化された列に挿入することはできず、.NET 4.6.1以降のクライアントを使用する必要があることを理解していますが、一括挿入操作もできないかどうか知りたいですか?

私のために働いたサンプルコード
(Windows10の要求を満たすため)

        SqlCommand cmd;
        SqlConnection conn;
        SqlBulkCopy copy;
        SqlDataAdapter da;
        DataTable dt;

        using (conn = new SqlConnection(ConfigurationManager.ConnectionStrings["Database"].ConnectionString))
        {
            conn.Open();

            using (cmd = new SqlCommand("SELECT * FROM members", conn))
            using (copy = new SqlBulkCopy(conn))
            using (da = new SqlDataAdapter(cmd))
            using (dt = new DataTable())
            {
                cmd.CommandTimeout = 600;

                da.Fill(dt);

                cmd.CommandText = "TRUNCATE TABLE membersE";
                cmd.ExecuteNonQuery();

                copy.DestinationTableName = "membersE";
                copy.WriteToServer(dt);                    
            }
        }
4
RoastBeast

説明している方法での一括挿入操作は、SSMSを介した暗号化列ではサポートされていません。

この( https://blogs.msdn.Microsoft.com/sqlsecurity/2015/07/28/encrypting-existing-data-with-always-encrypted/ )の記事を参照して、既存の常に暗号化するデータ

また、C#(.NET 4.6.1+クライアント)アプリを介した一括挿入の実行もサポートされていることに注意してください。

具体的にはSqlBulkCopy.WriteToServer(IDataReader)メソッドを使用して、SqlBulkCopyを使用してc#でこれを行うことができます。私はあなたがcsvファイルから暗号化された列(たとえばencryptedTable)を持つテーブルにデータをロードしようとしていると仮定しています。私は次のようにします

  • 列を暗号化せずに同じスキーマで新しいテーブルを作成します(たとえば、セキュリティ上の理由から、unencryptedTable、このテーブルをローカルSQLサーバーインスタンスで作成することを検討してください)。
  • 質問で説明した方法を使用して、csvデータをunencryptedTableにロードします。
  • _select * from unencryptedTable_を実行してSqlDataReaderにデータをロードし、次にSqlBulkCopyを使用して、SqlBulkCopy.WriteToServer(IDataReader)メソッドを使用してそれをencryptedTableにロードします。

これに関して他に質問がある場合は、コメントセクションに質問を投稿してください。できる限り対応させていただきます。