This is a read-only copy of the MariaDB Knowledgebase generated on 2024-11-14. For the latest, interactive version please visit https://mariadb.com/kb/.

Columnas Dinamicas

Las columnas dinámicas permiten poder guardar un conjunto de columnas para cada fila de una tabla. Funciona guardando un conjunto de columnas en un tipo de dato blob y contando con una pequeña serie de funciones para manipularlas.

Las columnas dinámicas deben ser usadas cuando no sea posible utilizar columnas estándar o regulares.

Un caso típico para esto es cuando uno necesita guardar datos que tengan diferentes atributos (colores, tamaños, peso, etc), y las diferentes posibilidades son muy grandes o desconocidas en cierto modo. En ese caso estos datos se pueden guardar en columnas dinámicas.

Columnas Dinamicas

La tabla debe contener una columna del tipo blob que se utilizara para guardar las columnas dinamicas:

create table assets (
  item_name     varchar(32) primary key, -- Un atributo comun a todos los items
  dynamic_cols  blob  -- Aca se guardaran las columnas dinamicas
);

Una vez creada la columna, se puede acceder a la misma con una sere de funciones de columnas dinámicas.

Insertar un registro con dos columnas dinámicas: color=blue, size=XL

insert into assets values ('MariaDB T-shirt', COLUMN_CREATE('color', 'blue', 'size', 'XL'));

Insertar otro registro con columnas dinámicas: color=blue, price=500

insert into assets values ('Thinkpad Laptop', COLUMN_CREATE('color', 'black', 'price', 500));

Seleccionado sobre la columna dinamica 'color' para todos los items:

MariaDB [test]> select item_name, COLUMN_GET(dynamic_cols, 'color' as char) as color from assets;
+-----------------+-------+
| item_name       | color |
+-----------------+-------+
| MariaDB T-shirt | blue  |
| Thinkpad Laptop | black |
+-----------------+-------+
2 rows in set (0.00 sec)

(nota: el ejemplo de arriba utiliza MariaDB 10.0.1. En MariaDB 5.3, las columnas solo pueden ser identificadas por numeros. Ver #mariadb-53-vs-mariadb-100 en la seccion inferior)

Es posible agregar y remover columnas dinámicas de una fila:

-- Remover una columna:
update assets set dynamic_cols=COLUMN_DELETE(dynamic_cols, "price") 
where COLUMN_GET(dynamic_cols, 'color' as char)='black'; 

-- Agregar una columna:
update assets set dynamic_cols=COLUMN_ADD(dynamic_cols, 'warranty', '3 years')
where item_name='Thinkpad Laptop';

También se pueden listar todas las columnas o (desde MariaDB 10.0.1) traerlas juntas con sus valores en formato JSON:

MariaDB [test]> select item_name, column_list(dynamic_cols) from assets;
+-----------------+---------------------------+
| item_name       | column_list(dynamic_cols) |
+-----------------+---------------------------+
| MariaDB T-shirt | `size`,`color`            |
| Thinkpad Laptop | `color`,`warranty`        |
+-----------------+---------------------------+
2 rows in set (0.00 sec)

MariaDB [test]> select item_name, COLUMN_JSON(dynamic_cols) from assets;
+-----------------+----------------------------------------+
| item_name       | COLUMN_JSON(dynamic_cols)              |
+-----------------+----------------------------------------+
| MariaDB T-shirt | {"size":"XL","color":"blue"}           |
| Thinkpad Laptop | {"color":"black","warranty":"3 years"} |
+-----------------+----------------------------------------+
2 rows in set (0.00 sec)

Referencia para columnas dinámicas

El resto de esta pagina es una referencia completa sobre columnas dinamicas en MariaDB

Funciones para columnas dinámicas:

COLUMN_CREATE

COLUMN_CREATE(column_nr, value [as type], [column_nr, value [as type]]...);
COLUMN_CREATE(column_name, value [as type], [column_name, value [as type]]...);

Return a dynamic columns blob that stores the specified columns with values.

El valor obtendo puede ser utilizado para:

  • nada
    • guardar en una tabla
    • futuras modificaciones con otras funciones para columnas dinamicas.

The as type part allows one to specify the value type. In most cases, this is redundant because MariaDB will be able to deduce the type of the value. Explicit type specification may be needed when the type of the value is not apparent. For example, a literal '2012-12-01' has a CHAR type by default, one will need to specify '2012-12-01' AS DATE to have it stored as a date. See the Datatypes section for further details.

Usos tipicos:

-- MariaDB 5.3+:
INSERT INTO tbl SET dyncol_blob=COLUMN_CREATE(1 /*column id*/, "value");
-- MariaDB 10.0.1+:
INSERT INTO tbl SET dyncol_blob=COLUMN_CREATE("column_name", "value");

COLUMN_ADD

COLUMN_ADD(dyncol_blob, column_nr, value [as type], [column_nr, value [as type]]...);
COLUMN_ADD(dyncol_blob, column_name, value [as type], [column_name, value [as type]]...);

Adds or updates dynamic columns.

    • dyncol_blob must be either a valid dynamic columns blob (for example, COLUMN_CREATE returns such blob), or an empty string.
    • column_name specifies the name of the column to be added. If dyncol_blob already has a column with this name, it will be overwritten.
    • value specifies the new value for the column. Passing a NULL value will cause the column to be deleted.
    • as type is optional. See #datatypes section for a discussion about types.

The return value is a dynamic column blob after the modifications.

Typical usage:

-- MariaDB 5.3+:
UPDATE tbl SET dyncol_blob=COLUMN_ADD(dyncol_blob, 1 /*column id*/, "value") WHERE id=1;
-- MariaDB 10.0.1+:
UPDATE t1 SET dyncol_blob=COLUMN_ADD(dyncol_blob, "column_name", "value") WHERE id=1;

Note: COLUMN_ADD() is a regular function (just like CONCAT()), hence, in order to update the value in the table you have to use the UPDATE ... SET dynamic_col=COLUMN_ADD(dynamic_col, ....) pattern.

COLUMN_GET

COLUMN_GET(dyncol_blob, column_nr as type);
COLUMN_GET(dyncol_blob, column_name as type);

Get the value of a dynamic column by its name. If no column with the given name exists, NULL will be returned.

column_name as type requires that one specify the datatype of the dynamic column they are reading.

This may seem counter-intuitive: why would one need to specify which datatype they're retrieving? Can't the dynamic columns system figure the datatype from the data being stored?

The answer is: SQL is a statically-typed language. The SQL interpreter needs to know the datatypes of all expressions before the query is run (for example, when one is using prepared statements and runs "select COLUMN_GET(...)", the prepared statement API requires the server to inform the client about the datatype of the column being read before the query is executed and the server can see what datatype the column actually has).

See the Datatypes section for more information about datatypes.

COLUMN_DELETE

COLUMN_DELETE(dyncol_blob, column_nr, column_nr...);
COLUMN_DELETE(dyncol_blob, column_name, column_name...);

Delete a dynamic column with the specified name. Multiple names can be given.

The return value is a dynamic column blob after the modification.

COLUMN_EXISTS

COLUMN_EXISTS(dyncol_blob, column_nr);
COLUMN_EXISTS(dyncol_blob, column_name);

Check if a column with name column_name exists in dyncol_blob. If yes, return 1, otherwise return 0.

COLUMN_LIST

COLUMN_LIST(dyncol_blob);

Before MariaDB 10.0.1: Return a comma-separated list of column numbers. After MariaDB 10.0.1: Return a comma-separated list of column names. The names are quoted with backticks.

Example using MariaDB 10.0.1:

MariaDB [test]> select column_list(column_create('col1','val1','col2','val2'));
+---------------------------------------------------------+
| column_list(column_create('col1','val1','col2','val2')) |
+---------------------------------------------------------+
| `col1`,`col2`                                           |
+---------------------------------------------------------+
MariaDB starting with 10.0.1

COLUMN_CHECK

COLUMN_CHECK(dyncol_blob);

Check if dyncol_blob is a valid packed dynamic columns blob. Return value of 1 means the blob is valid, return value of 0 means it is not.

Rationale: Normally, one works with valid dynamic column blobs. Functions like COLUMN_CREATE, COLUMN_ADD, COLUMN_DELETE always return valid dynamic column blobs. However, if a dynamic column blob is accidentally truncated, or transcoded from one character set to another, it will be corrupted. This function can be used to check if a value in a blob field is a valid dynamic column blob.

This function was introduced in MariaDB 10.0.1.

COLUMN_JSON

COLUMN_JSON(dyncol_blob);

Return a JSON representation of data in dyncol_blob.

Example:

MariaDB [test]> select item_name, COLUMN_JSON(dynamic_cols) from assets;
+-----------------+----------------------------------------+
| item_name       | COLUMN_JSON(dynamic_cols)              |
+-----------------+----------------------------------------+
| MariaDB T-shirt | {"size":"XL","color":"blue"}           |
| Thinkpad Laptop | {"color":"black","warranty":"3 years"} |
+-----------------+----------------------------------------+

Limitation: COLUMN_JSON will decode nested dynamic columns at a nesting level of not more than 10 levels deep. Dynamic columns that are nested deeper than 10 levels will be shown as BINARY string, without encoding.

This function was introduced in MariaDB 10.0.1.

Nesting dynamic columns

It is possible to use nested dynamic columns by putting one dynamic column blob inside another. The COLUMN_JSON function will display nested columns.

MariaDB [test]> set @tmp= column_create('parent_column', column_create('child_column', 12345));
Query OK, 0 rows affected (0.00 sec)

MariaDB [test]> select column_json(@tmp);
+------------------------------------------+
| column_json(@tmp)                        |
+------------------------------------------+
| {"parent_column":{"child_column":12345}} |
+------------------------------------------+
1 row in set (0.00 sec)

MariaDB [test]> select column_get(column_get(@tmp, 'parent_column' as char), 'child_column' as int);
+------------------------------------------------------------------------------+
| column_get(column_get(@tmp, 'parent_column' as char), 'child_column' as int) |
+------------------------------------------------------------------------------+
|                                                                        12345 |
+------------------------------------------------------------------------------+
1 row in set (0.00 sec)

Datatypes

In SQL, one needs to define the type of each column in a table. Dynamic columns do not provide any way to declare a type in advance ("whenever there is a column 'weight', it should be integer" is not possible). However, each particular dynamic column value is stored together with its datatype.

The set of possible datatypes is the same as that used by the SQL CAST and CONVERT functions:

typedynamic column internal typedescription
BINARY[(N)]DYN_COL_STRING(variable length string with binary charset)
CHAR[(N)]DYN_COL_STRING(variable length string with charset)
DATEDYN_COL_DATE(date - 3 bytes)
DATETIME[(D)]DYN_COL_DATETIME(date and time (with microseconds) - 9 bytes)
DECIMAL[(M[,D])]DYN_COL_DECIMAL(variable length binary decimal representation with MariaDB limitation)
DOUBLE[(M,D)]DYN_COL_DOUBLE(64 bit double-precision floating point)
INTEGERDYN_COL_INT(variable length, up to 64 bit signed integer)
SIGNED [INTEGER]DYN_COL_INT(variable length, up to 64 bit signed integer)
TIME[(D)]DYN_COL_TIME(time (with microseconds, may be negative) - 6 bytes)
UNSIGNED [INTEGER]DYN_COL_UINT(variable length, up to 64bit unsigned integer)

A note about lengths

If you're running queries like

SELECT COLUMN_GET(blob, 'colname' as CHAR) ... 

without specifying a maximum length (i.e. using #as CHAR#, not as CHAR(n)), MariaDB will report the maximum length of the resultset column to be 53,6870,911 (bytes or characters?) for MariaDB 5.3-10.0.0 and 16,777,216 for MariaDB 10.0.1+. This may cause excessive memory usage in some client libraries, because they try to pre-allocate a buffer of maximum resultset width. If you suspect you're hitting this problem, use CHAR(n) whenever you're using COLUMN_GET in the select list.

MariaDB 5.3 vs MariaDB 10.0

The dynamic columns feature was introduced into MariaDB in two steps:

  1. MariaDB 5.3 was the first version to support dynamic columns. Only numbers could be used as column names in this version.
  2. In MariaDB 10.0.1, column names can be either numbers or strings. Also, the COLUMN_JSON and COLUMN_CHECK functions were added.

See also Dynamic Columns in MariaDB 10.

Client-side API

It is also possible to create or parse dynamic columns blobs on the client side. libmysql client library now includes an API for writing/reading dynamic column blobs. See dynamic-columns-api for details.

Limitations

DescriptionLimit
Max number of columns 65535
Max total length of packed dynamic columnmax_allowed_packet (1G)
Content reproduced on this site is the property of its respective owners, and this content is not reviewed in advance by MariaDB. The views, information and opinions expressed by this content do not necessarily represent those of MariaDB or any other party.