Mysql 'VALUES function' is deprecated

Question:

This is my python code which prints the sql query.

def generate_insert_statement(column_names, values_format, table_name, items, insert_template=INSERT_TEMPLATE, ):
    return insert_template.format(
        column_names=",".join(column_names),
        values=",".join(
            map(
                lambda x: generate_raw_values(values_format, x),
                items
            )
        ),
        table_name=table_name,
        updates_on=create_updates_on_columns(column_names)
    )
query = generate_insert_statement(table_name=property['table_name'],
        column_names=property['column_names'],
        values_format=property['values_format'], items=batch)
        print(query) #here
        execute_commit(query)

When printing the Mysql query my Django project shows following error in the terminal:

'VALUES function' is deprecated and will be removed in a future release. Please use an alias (INSERT INTO ... VALUES (...) AS alias) and replace VALUES(col) in the ON DUPLICATE KEY UPDATE clause with alias.col instead

Mysql doumentation does not say much about it.What does this mean and how to can i rectify it.

INSERT_TEMPLATE = "INSERT INTO {table_name} ({column_names}) VALUES {values} ON DUPLICATE KEY UPDATE {updates_on};"
Asked By: Pravin Mishra

||

Answers:

Basically, mysql is looking toward removing a longstanding non-standard use of the values function to clear the way for some future work where the SQL standard allows using a VALUES keyword for something very different, and because how the VALUES function works in subqueries or not in a ON DUPLICATE KEY UPDATE clause can be surprising.

You need to add an alias to the VALUES clause and then use that alias instead of the non-standard VALUES function in the ON DUPLICATE KEY UPDATE clause, e.g. change

INSERT INTO foo (bar, baz) VALUES (1,2)
ON DUPLICATE KEY UPDATE baz=VALUES(baz)

to

INSERT INTO foo (bar, baz) VALUES (1,2) AS new_foo
ON DUPLICATE KEY UPDATE baz=new_foo.baz

(This only works on mysql 8+, not on older versions or in any version of mariadb through at least 10.8.3)

Note that this is no different if you are updating multiple rows:

INSERT INTO foo (bar, baz) VALUES (1,2),(3,4),(5,6) AS new_foo
ON DUPLICATE KEY UPDATE baz=new_foo.baz

From https://dev.mysql.com/worklog/task/?id=13325:

According to the SQL standard, VALUES is a table value constructor that returns a table. In MySQL this is true for simple INSERT and REPLACE statements, but MySQL also uses VALUES to refer to values in INSERT … ON DUPLICATE KEY UPDATE statements. E.g.:

INSERT INTO t(a,b) VALUES (1, 2) ON DUPLICATE KEY
UPDATE a = VALUES (b) + 1;

VALUES (b) refers to the value for b in the table value constructor for the INSERT, in this case 2.

To make the value available in simple arithmetic expressions, it is part of the parser rule for simple_expr. Unfortunately, this also means that VALUES can be used in this way in a lot of other statements, e.g.:

SELECT a FROM t WHERE a=VALUES(a);

In all such statements, VALUES returns NULL, so the above query would not have the intended effect. The only meaningful usage of VALUES as a function, rather than a table value constructor, is in INSERT … ON DUPLICATE KEY UPDATE. Also, the non-standard use in INSERT … ON DUPLICATE KEY UPDATE does not extend to subqueries. E.g.:

INSERT INTO t1 VALUES(1,2) ON DUPLICATE KEY
UPDATE a=(SELECT a FROM t2 WHERE b=VALUES(b));

This does not do what the user expects. VALUES(b) will return NULL, even if it is in an INSERT .. ON DUPLICATE KEY UPDATE statement.

The non-standard syntax also makes it harder (impossible?) to implement standard behavior of VALUES as specified in feature F641 "Row and table constructors".

Answered By: ysth
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.