Home > OS >  SQLite: UNNEST an integer array represented as a BLOB
SQLite: UNNEST an integer array represented as a BLOB

Time:07-06

SQLite doesn’t have native support for arrays. I would think that my method (thinking outlined below) of making a custom BLOB encoding would be a fairly common workaround (yes, I need an array rather than normalizing the table). The benefit of representing an integer array as a BLOB is primarily the space savings, for example:

13,24,455,23,64789

stored as TEXT will take up 18 bytes (commas included, making assumptions here)

but if one were to store the above TEXT in a custom encoded BLOB format it would look like this:

0x000D001801C7FD15

Where every number is assumed to take up 2 Bytes (0 to 65,535 or 0000 to FFFF). This BLOB, to my understanding, would then be 10 Bytes nearly half as small as storing it as TEXT. This would also magnify with the number of rows

My question then is this:

Is there a good way of unnesting a BLOB by width? Say that I want to unnest the BLOB so that each row represents an integer. Can I take the above BLOB and turn it into this?

id number
1 000D
2 0018
3 01C7
4 FD15

CodePudding user response:

SQLite's HEX() function

interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob.

After you get the blob as a string use SUBSTR() to slice it in 4 char parts:

WITH cte(id) AS (VALUES (1), (2), (3), (4), (5))
SELECT HEX(t.col) hex_col, 
       c.id,
       SUBSTR(HEX(t.col), (c.id - 1) * 4   1, 4) number
FROM tablename t JOIN cte c
ORDER BY t.rowid, c.id;

Or, with a recursive CTE to generate dynamically the list of values 1..n:

WITH cte(id) AS (
  SELECT 1 
  UNION ALL
  SELECT id   1
  FROM cte
  WHERE id < 5
)
SELECT HEX(t.col) hex_col, 
       c.id,
       SUBSTR(HEX(t.col), (c.id - 1) * 4   1, 4) number
FROM tablename t JOIN cte c
ORDER BY t.rowid, c.id;

Change col to the name of your blob column.

See the demo.

  • Related