I have a SQL Server 2016 database with "Always Encrypted" set to on. We have multiple encrypted columns and a stored procedure that handles updates.
CREATE PROCEDURE UpdateRecord
@ID INT,
@EncryptedParameter01 NVARCHAR(255) = NULL,
@EncryptedParameter02 NVARCHAR(255) = NULL,
@EncryptedParameter03 NVARCHAR(255) = NULL,
@EncryptedParameter04 NVARCHAR(255) = NULL,
@EncryptedParameter05 NVARCHAR(255) = NULL,
@EncryptedParameter06 NVARCHAR(255) = NULL,
@EncryptedParameter07 NVARCHAR(255) = NULL,
@EncryptedParameter08 NVARCHAR(255) = NULL,
@EncryptedParameter09 NVARCHAR(255) = NULL,
@EncryptedParameter10 NVARCHAR(255) = NULL,
@EncryptedParameter11 NVARCHAR(255) = NULL,
@EncryptedParameter12 NVARCHAR(255) = NULL,
@EncryptedParameter13 NVARCHAR(255) = NULL,
@EncryptedParameter14 NVARCHAR(255) = NULL,
@EncryptedParameter15 NVARCHAR(255) = NULL,
@EncryptedParameter16 NVARCHAR(255) = NULL,
@EncryptedParameter17 NVARCHAR(255) = NULL,
@EncryptedParameter18 NVARCHAR(255) = NULL,
@EncryptedParameter19 NVARCHAR(255) = NULL,
@EncryptedParameter20 NVARCHAR(255) = NULL
AS
BEGIN
UPDATE myTable
SET Field01 = CASE WHEN @EncryptedParameter01 IS NULL THEN Field01 ELSE @EncryptedParameter01 END,
Field02 = CASE WHEN @EncryptedParameter02 IS NULL THEN Field02 ELSE @EncryptedParameter02 END,
Field03 = CASE WHEN @EncryptedParameter03 IS NULL THEN Field03 ELSE @EncryptedParameter03 END,
Field04 = CASE WHEN @EncryptedParameter04 IS NULL THEN Field04 ELSE @EncryptedParameter04 END,
Field05 = CASE WHEN @EncryptedParameter05 IS NULL THEN Field05 ELSE @EncryptedParameter05 END,
Field06 = CASE WHEN @EncryptedParameter06 IS NULL THEN Field06 ELSE @EncryptedParameter06 END,
Field07 = CASE WHEN @EncryptedParameter07 IS NULL THEN Field07 ELSE @EncryptedParameter07 END,
Field08 = CASE WHEN @EncryptedParameter08 IS NULL THEN Field08 ELSE @EncryptedParameter08 END
, Field09 = CASE WHEN @EncryptedParameter09 IS NULL THEN Field09 ELSE @EncryptedParameter09 END
, Field10 = CASE WHEN @EncryptedParameter10 IS NULL THEN Field10 ELSE @EncryptedParameter10 END
, Field11 = CASE WHEN @EncryptedParameter11 IS NULL THEN Field11 ELSE @EncryptedParameter11 END
, Field12 = CASE WHEN @EncryptedParameter12 IS NULL THEN Field12 ELSE @EncryptedParameter12 END
, Field13 = CASE WHEN @EncryptedParameter13 IS NULL THEN Field13 ELSE @EncryptedParameter13 END
, Field14 = CASE WHEN @EncryptedParameter14 IS NULL THEN Field14 ELSE @EncryptedParameter14 END
, Field15 = CASE WHEN @EncryptedParameter15 IS NULL THEN Field15 ELSE @EncryptedParameter15 END
, Field16 = CASE WHEN @EncryptedParameter16 IS NULL THEN Field16 ELSE @EncryptedParameter16 END
, Field17 = CASE WHEN @EncryptedParameter17 IS NULL THEN Field17 ELSE @EncryptedParameter17 END
, Field18 = CASE WHEN @EncryptedParameter18 IS NULL THEN Field18 ELSE @EncryptedParameter18 END
, Field19 = CASE WHEN @EncryptedParameter19 IS NULL THEN Field19 ELSE @EncryptedParameter19 END
, Field20 = CASE WHEN @EncryptedParameter20 IS NULL THEN Field20 ELSE @EncryptedParameter20 END
WHERE ID = @ID
END
Our actual stored procedure is more complex, this just gives you an idea. If this is called with only a handful of parameters it works fine. However if it is called with more than 10 the procedure fails.
The error message is
Msg 206, Level 16, State 2, Procedure UpdateRecord, Line 0 [Batch Start Line 0]
Operand type clash: nvarchar is incompatible with nvarchar(255) encrypted with (encryption_type = 'DETERMINISTIC', encryption_algorithm_name = 'AEAD_AES_256_CBC_HMAC_SHA_256', column_encryption_key_name = 'MyNamedKey', column_encryption_key_database_name = 'MyDatabase')
This is not down to individual parameters failing, rather the number of characters being passed. Also this procedure was working fine before the encryption was added.
Any further info on why this is happening and work arounds gratefully received.
Many thanks.
Edited to include call:
I am seeing this both through VB and T-SQL. Simplest case being a direct call from SSMS. I do have "Enable Parameterization for Always Encrypted" checked. The parameters are being passed in correctly, and functions correctly, provided 10 or less parameters are sent. Example call:
DECLARE @PassedEncryptedParameter01 NVARCHAR(255) = 'Updated value 01'
EXEC UpdateRecord @Id=12345, @EncryptedParameter01 = @PassedEncryptedParameter01
As you can see I have the declared the type so it matches. The issue here isn't how the parameters are defined, rather the number of parameters being sent.