SQL differences

Comparing a Text Column With the Number 0 Matches Codes Like abc on MySQL and Fails on PostgreSQL

Product codes are text, and a query that forgets the quotes, WHERE code = 0, still runs on MySQL and MariaDB. There it returns codes that have nothing to do with 0.

MySQL and MariaDB turn the text into a number, and text that does not start with digits becomes 0, so WHERE code = 0 finds every code like 'abc'. SQLite compares the number as text and finds nothing. PostgreSQL refuses to compare character varying with integer. '1' = 1 trips over the same thing in another way: false on SQLite, true on the other three.

SELECT COUNT(*) FROM items WHERE code = 0, run on four engines: SQLite 3.45.1 0; PostgreSQL 16.15 error: operator does not exist: character varying = integer; MySQL 8.0.46 1; MariaDB 10.11.14 1.

What Each Engine Answered

On a table made with

CREATE TABLE items (code VARCHAR(10));
INSERT INTO items VALUES ('abc');

the example

SELECT COUNT(*) FROM items WHERE code = 0;

gave these answers:

Engine Answer
SQLite 3.45.1 0
PostgreSQL 16.15 error: operator does not exist: character varying = integer
MySQL 8.0.46 1
MariaDB 10.11.14 1

Every Form BareSQL Checks

BareSQL Portable checks 3 forms of this, and each was run on all four engines. yes means the engine ran it and the engines that ran it agreed, no means the engine refused it, and a value is what the engine answered where they disagreed.

Form SQLite PostgreSQL MySQL MariaDB
text column = number 0 no 1 1
'1' = 1 0 true 1 1
'abc' = number 0 no 1 1

What to Write Instead

This form answers the same on every engine:

SELECT COUNT(*) FROM items WHERE code = '0';
Engine Answer
SQLite 3.45.1 0
PostgreSQL 16.15 0
MySQL 8.0.46 0
MariaDB 10.11.14 0

Compare like with like: quote the number when the column holds text (code = '0'), or convert one side with CAST.

What BareSQL Portable Reports

Saved as example.sql, the example gets this from baresql lint --all:

$ baresql lint --all example.sql
example.sql:3:34: error: code = 0 compares a text column with a number: MySQL and MariaDB turn the text into a number, so 'abc' matches 0, SQLite compares it as text and finds nothing, and PostgreSQL refuses it. [text-number-compare]
    code = 0
    Compare like with like: quote the number when the column holds text (code = '0'), or convert one side with CAST.

1 problem: 1 error.

baresql rules text-number-compare prints the same answers in the terminal, and the BareSQL Portable page lists every difference BareSQL knows.