In an always-confidential database cluster, you can change an existing column's encryption state using ALTER TABLE ... ALTER COLUMN. The operation works in both directions: encrypt a plaintext column or decrypt a ciphertext column back to plaintext.
Prerequisites
Before you begin, ensure that you have:
-
The always-confidential database feature enabled and configured for your PolarDB for PostgreSQL cluster. For setup instructions, see Enable the always-confidential database feature. To mark columns as sensitive, see Define sensitive data. To configure client-side access, see Use the always-confidential database feature from a client
-
A PolarDB for PostgreSQL cluster at minor version 20231030 (14.9.14.0) or later
-
Authorization through a behavior control list (BCL). See Grant access permissions on multi-user data
How it works
The ALTER TABLE ... ALTER COLUMN ... USING statement changes the column type and transforms all existing data in a single operation. The result depends on the current encryption state and the target type you specify:
| Current state | Target type | Result |
|---|---|---|
| Plaintext | Ciphertext (e.g., enc_int4) |
Encrypts the column |
| Ciphertext | Original plaintext (e.g., int4) |
Decrypts the column |
The following table lists the supported type pairs and their corresponding conversion functions.
| Plaintext type | Ciphertext type | Encrypt function | Decrypt function |
|---|---|---|---|
| int4 | enc_int4 | encdb.enc_int4_encrypt | encdb.decrypt |
| int8 | enc_int8 | encdb.enc_int8_encrypt | encdb.decrypt |
| float4 | enc_float4 | encdb.enc_float4_encrypt | encdb.decrypt |
| float8 | enc_float8 | encdb.enc_float8_encrypt | encdb.decrypt |
| numeric | enc_decimal | encdb.enc_decimal_encrypt | encdb.decrypt |
| text | enc_text | encdb.enc_text_encrypt | encdb.decrypt |
| timestamp | enc_timestamp | encdb.enc_timestamp_encrypt | encdb.decrypt |
Syntax
ALTER TABLE <table_name>
ALTER COLUMN <column_name> [SET DATA] TYPE <target_type>
USING <conversion_function>(<column_name>[, <keyname>]);
Parameter notes:
-
To decrypt (ciphertext to plaintext): pass only
column_nameto the conversion function -
To encrypt (plaintext to ciphertext): pass
column_namealone to use the default database key, or pass bothcolumn_nameandkeynameto use a specific key
Examples
Encrypt a column using a custom key
Use a custom key to control the encryption algorithm (for example, deterministic vs. random) and the master encryption key (MEK).
Step 1: Generate a keyname.
SELECT encdb.keyname_generate(<user_name>, <database_name>, <schema_name>, <table_name>, <column_name>);
Replace the placeholders with the actual values for your column. For example:
SELECT encdb.keyname_generate('alice', 'patients_db', 'public', 'patients', 'ssn');
Step 2: Generate a data encryption key (DEK) for the keyname.
SELECT encdb.dek_generate(<keyname>[, <json_params>]);
The json_params argument is optional. Pass a JSON object to customize the key:
| Key | Description | Default | Valid values |
|---|---|---|---|
algorithm |
Encryption algorithm | AES_128_GCM |
AES_128_GCM, AES_128_ECB, AES_128_CTR, AES_128_CBC, SM4_128_CBC, SM4_128_ECB, SM4_128_CTR, CLWW_ORE |
policy |
Encryption policy (reserved) | DEFAULT |
DEFAULT |
flags |
Encryption method | RND |
RND (random encryption), DET (deterministic encryption) |
mekid |
ID of the MEK used to generate DEKs | MEK ID of the current user | Any valid MEK ID |
CLWW_ORE implements order-revealing encryption (ORE), which preserves sort order on encrypted data. For details, see Practical Order-Revealing Encryption with Limited Leakage.
Step 3: Encrypt the column.
The following example converts the ssn column in the patients table from int4 to enc_int4 using the keyname generated in step 1.
ALTER TABLE patients
ALTER COLUMN ssn SET DATA TYPE enc_int4
USING encdb.enc_int4_encrypt(ssn, <keyname>);
Encrypt a column using the default database key
If you do not need a custom key, use the default key for the current database. The default keyname follows the format |<User>|<Database>|.
ALTER TABLE patients
ALTER COLUMN ssn SET DATA TYPE enc_int4
USING encdb.enc_int4_encrypt(ssn);
Decrypt a column
To convert a column back to plaintext, specify the original plaintext type and use encdb.decrypt. Pass only the column name — no keyname is required.
ALTER TABLE patients
ALTER COLUMN ssn SET DATA TYPE int4
USING encdb.decrypt(ssn);