2016-06-25

I'm going to need to use SQLite syntax for a project that I'm involved with, and predictably I wonder: how standard is it? The SQLite folks themselves make modest claims to support most of the features with a special focus on SQL-92, but (a) I like to do my own counting (b) there's no official standard named SQL-92 because it was superseded 17 years ago.

By ignoring SQL-92 claims I eschew use of the NIST test suite. I'll be far less strict and more arbitrary: I'll go through SQL:2011's "Feature taxonomy and definition for mandatory features". For each feature in that list, I'll come up with a simple example SQL statement. If SQLite appears to handle the example, I'll mark it "Okay", else I'll mark it "Fail". I'm hoping that arbitrariness equals objectivity, because the unfair pluses should balance the unfair minuses.

Skip to the end of this blog post if you just want to see the final score.

Standard SQL Core Features, Examples, and Okay/Fail Results

E-011 Numeric data types

E-011-01 INTEGER and SMALLINT

Example: create table t (s1 int);

Fail. A numeric column can contain non-numeric strings. There is a similar flaw for all data types, but let's count them all as only one fail.

E-011-02 REAL, DOUBLE PRECISON,and FLOAT data types

Example: create table tr (s1 float);

Okay.

E-011-03 DECIMAL and NUMERIC data types

Example: create table td (s1 numeric);

Okay, although: when there are many post-decimal digits there is a switch to exponential notation, for example after "insert into t3 values (0.0000000000000001);" and "select *from t3" I get "1.0e-16". I regard this as adisplay flaw rather than a fail.

E-011-04 Arithmetic operators

Example: select 10+1,9-2,8*3,7/2 from t;

Okay. SQLite is wrong to calculate that 7/0 is NULL, though.

E-011-05 Numeric comparison

Example: select * from t where 1
Okay.

E-011-06 Implicit casting among the numeric data types

Example: select * from t where s1 = 1.00;

Okay, but only because SQLite doesn't distinguish etween numeric data types.

E021 Character string types

E-021-01 Character data type (including all its spellings)

Example: create table t44 (s1 char);

Okay, but only because SQLite accepts any definition that includes the word 'CHAR', for example CREATE TABLE t (s1 BIGCHAR) is okay although there's no such data type. There are no checks on maximum length, and no padding for insertions with less than the maximum length.

E021-02 CHARACTER VARYING data type (including all its spellings)

Example: create table t45 (s1 varchar);

Okay, but the behaviour is exactly the same as for CHARACTER.

E021-03 Character literals

Example: insert into t45 values ('');

Okay, and the bad practice of accepting ""s for character literals is avoided.Even hex notation, for example X'41', is okay.

E021-04 CHARACTER_LENGTH function

Example: select character_length(s1) from t;

Fail. There is no such function. There is a function LENGTH(), which is okay.

E021-05 OCTET_LENGTH

Example: select octet_length(s1) from t;

Fail. There is no such function.

E021-06 SUBSTRING function.

Example: select substring(s1 from 1 for 1) from t;

Fail. There is no such function. There is a function SUBSTR(x,n,n) which is okay.

E021-07 Character concatenation

Example: select 'a' || 'b' from t;

Okay.

E021-08 UPPER and LOWER functions

Example: select upper('a'),lower('B') from t;

Okay. It does not work well out of the box, but I loaded the ICU extension.

E021-09 TRIM function

Example: select trim('a ') from t;

Okay.

E021-10 Implicit casting among the fixed-length and variable-length character string types

Example: select * from tm where char_column > varchar_column;

Okay, but only because SQLite doesn't distinguish between character data types.

E021-11 POSITION function

Example; select position(x in y) from z;

Fail. There is no such function.

E021-02 Character comparison

Example: select * from t where s1 > 'a';

Okay. I should note here that comparisons are case sensitive, and it is devilishly hard to change this except with ASCII,but case insensitivity is not a requirement for this feature.

E031 Identifiers

E031-01 Delimited

Example: create table "t47" (s1 int);

Fail. Although I can enclose identifiers inside double quotes, that doesn't make them case sensitive.

E031-02 Lower case identifiers

Example: create table t48 (s1 int);

Okay.

E031-03 Trailing underscore

Example: create table t49_ (s1 int);

Okay.

E051 Basic query specification

E051-01 SELECT DISTINCT

Example: select distinct s1 from t;

Okay.

E051-02 GROUP BY clause

Example: select distinct s1 from t group by s1;

Okay.

E051-04 GROUP BY can contain columns not in select list

Example: select s1 from t group by lower(s1);

Okay.

E051-05 select list items can be renamed

Example: select s1 as K from t order by K;

Okay.

E051-06 HAVING clause

Example: select s1,count(*) from t having s1
Fail. GROUP BY is mandatory before HAVING.

If I hadn't happened to omit GROUP BY, it would have been okay.

E051-07 Qualifie d * in select list

Example: select t.* from t;

Okay.

E051-08 Correlation names in the FROM clause

Example: select * from t as K;

Okay.

E051-09 Rename columns in the FROM clause

Example: select * from t as x(q,c);

Fail.

E061 Basic predicates and search conditions

E061-01 Comparison predicate

Example: select * from t where 0 = 0;

Okay. But less correct syntax would work too, for example "where 0 is 0".

E061-02 BETWEEN predicate

Example: select * from t where ' ' between '' and ' ';

Okay.

E061-03 IN predicate with list of values

Example: select * from t where s1 in ('a',upper('a'));

Okay.

E061-04 LIKE predicate

Example: select * from t where s1 like '_';

Okay.

E061-05 LIKE predicate: ESCAPE clause

Example: select * from t where s1 like '_' escape '_';

Okay.

E061-06 NULL predicate

Example: select * from t where s1 is not null;

Okay.

E061-07 Quantified comparison predicate

Example: select * from t where s1 = any (select s1 from t);

Fail. Syntax error.

E061-08 EXISTS predicate

Example: select * from t where not exists (select * from t);

Okay.

E061-09 Subqueries in comparison predicate

Example: select * from t where s1 > (select s1 from t);

Fail. There was more than one row in the subquery result set, but SQLite didn't return an error.

E061-11 Subqueries in IN predicate

Example: select * from t where s1 in (select s1 from t);

Okay.

E061-12 Subqueries in quantified comparison predicate

Example: select * from t where s1 >= all (select s1 from t);

Fail. Syntax error.

E061-13 Correlated subqueries

Example: select * from t where s1 = (select s1 from t2 where t2.s2 = t.s1);

Okay.

E061-14 Search condition

Example: select * from t where 0 0 or 'a'
Okay.

E071 Basic query expressions

E071-01 UNION DISTINCT table operator

Example: select * from t union distinct select * from t;

Fail. However, "select * from t union select * from t;" is okay.

E071-01 UNION ALL table operator

Example: select * from t union all select * from t;

Okay.

E071-03 EXCEPT DISTINCT table operator

Example: select * from t except distinct select * from t;

Fail. However, "select * from t except select * from t;" is okay.

E071-05 Columns combined via table operators need not have exactly the same data type.

Example: select s1 from t union select 5 from t;

Okay, but only because SQLite doesn't distinguish data types very well.

E071-06 Table operators in subqueries

Example: select * from t where 'a' in (select * from t union select * from t);

Okay.

E081 Basic privileges

E081-01 Select privilege at the table level

Fail. Syntax error. (SQLite doesn't support privileges.)

E081-02 DELETE privilege

Fail. (SQLite doesn't support privileges.)

E081-03 INSERT privilege at the table level

Fail. (SQLite doesn't support privileges.)

E081-04 UPDATE privilege at the table level

Fail. (SQLite doesn't support privileges.)

E081-05 UPDATE privilege at column level

Fail. (SQLite doesn't support privileges.)

E081-06 REFERENCES privilege at the table level

Fail. (SQLite doesn't support privileges.)

E081-07 REFERENCES privilege at column level

Fail. (SQLite doesn't support privileges.)

E081-08 WITH GRANT OPTION

Fail. (SQLite doesn't support privileges.)

E081-09 USAGE privilege

Fail. (SQLite doesn't support privileges.)

E081-10 EXECUTE privilege

Fail. (SQLite doesn't support privileges.)

E091 Set functions

E091-01 AVG

Example: select avg(s1) from t7;

Fail. No warning that nulls were eliminated.

E091-02 COUNT

Example: select count(*) from t7 where s1 > 0;

Okay.

E091-03 MAX

Example: select max(s1) from t7 where s1 > 0;

Okay.

E091-04 MIN

Example: select min(s1) from t7 where s1 > 0;

Okay.

E091-05 SUM

Example: select sum(1) from t7 where s1 > 0;

Okay.

E091-06 ALL quantifier

Example: select sum(all s1) from t7 where s1 > 0;

Okay.

E091-07 DISTINCT quantifier

Example: select sum(distinct s1) from t7 where s1 > 0;

Okay.

E101 Basic data manipulation

E101-01 INSERT statement

Example: insert into t (s1) values (''),(null),(55);

Okay.

E101-03 Searched UPDATE statement

Example: update t set s1 = null where s1 in (select s1 from t2);

Okay.

E01-04 Searched DELETE statement

Example: delete from t where s1 in (select s1 from t);

Okay.

E111 Single row SELECT statement

Example: select count(*) from t;

Okay.

E121 Basic cursor support

E121-01 DECLARE CURSOR

Fail. SQLite doesn't support cursors.

E121-02 ORDER BY columns need not be in select list

Example: select s1 from t order by s2;

Okay. Update on 2016-06-27: Originally I wrongly said "Fail", see the comments.

E121-03 Value expressions in select list

Example: select s1 from t7 order by -s1;

Okay.

E121-04 OPEN statement

Fail. SQLite doesn't support cursors.

E121-06 Positioned UPDATE statement

Fail. SQLite doesn't support cursors.

E121-07 Positioned DELETE statement

Fail. SQLite doesn't support cursors.

E121-08 CLOSE statement

Fail. SQLite doesn't support cursors.

E121-10 FETCH statement implicit next

Fail. SQLite doesn't support cursors.

E121-17 WITH HOLD cursors

Fail. SQLite doesn't support cursors.

E131 Null value support (nulls in lieu of values)

Example: select s1 from t7 where s1 is null;

Okay.

E141 Basic integrity constraints

E141-01 NOT NULL constraints

Example: create table t8 (s1 int not null);

Okay.

E141-02 UNIQUE constraints of NOT NULL columns

Example: create table t9 (s1 int not null unique);

Okay.

E141-03 PRIMARY KEY constraints

Example: create table t10 (s1 int primary key);

Okay, although SQLite wrongly assumes s1 is auto-increment.

E141-04 Basic FOREIGN KEY constraint with the NO ACTION default for both referential delete action and referential update action.

Example: create table t11 (s1 int references t10);

Fail. The foreign-key check will only be checked when I have said "pragma foreign_keys = on;".

E141-06 CHECK constraints

Example: create table t12 (s1 int, s2 int, check (s1 = s2));

Okay.

E141-07 Column defaults

Example: create table t13 (s1 int, s2 int default -1);

Okay.

E141-08 NOT NULL inferred on primary key

Example: create table t14 (s1 int primary key);

Fail. I am able to insert NULL if I don't explicitly say the column is NOT NULL.

E141-10 Names in a foreign key can be specified in any order

Example: create table t15 (s1 int, s2 int, primary key (s1,s2));

create table t16 (s1 int, s2 int, foreign key (s2,s1) references t15 (s1,s2));

Okay.

E151 Transaction support

E151-01 COMMIT statement

Example: commit;

Fail. I have to say BEGIN TRANSACTION first.

E151-02 ROLLBACK statement

Example: rollback;

Okay.

E152 Basic SET TRANSACTION statement

E152-01 SET TRANSACTION statement ISOLATION SERIALIZABLE clause

Example: set transaction isolation level serializable;

Fail. Syntax error.

E152-02 SET TRANSACTION statement READ ONLY and READ WRITE clauses

Example: set transaction read only;

Fail. Syntax error.

E153 Updatable queries with subqueries

E161 SQL comments using leading double minus

Example: --comment;

Okay.

E171 SQLSTATE suport

Example: drop table no_such_table;

Fail. At least, the error message doesn't hint that SQLSTATE exists.

E182 Host language binding

Okay. The existence of shell executable proves there is a C binding.

F031 Basic schema manipulation

F031-01 CREATE TABLE statement to create persistent base tables

Example: create table t20 (t20_1 int not null);

Okay.

F031-02 CREATE VIEW statement

Example: create view t21 as select * from t20;

Okay.

F031-03 GRANT statement

Fail. SQLite doesn't support privileges.

F031-04 ALTER TABLE statement: add column

Example: alter table t7 add column t7_2 varchar default 'q';

Okay.

F031-14 DROP TABLE statement: RESTRICT clause

Example: drop table t20 restrict;

Fail. Syntax error, and RESTRICT is not assumed.

F031-14 DROP VIEW statement: RESTRICT clause

Example: drop view v2 restrict;

Fail. Syntax error, and RESTRICT is not assumed.

F031-10 REVOKE statement: RESTRICT clause

Fail. SQLite does not support privileges.

F041 Basic joined table

F041-01 Inner join but not necessarily the INNER keyword

Example: select a.s1 from t7 a join t7 b;

Okay.

F041-02 INNER keyword

Example: select a.s1 from t7 a inner join t7 b;

Okay.

F041-03 LEFT OUTER JOIN

Example: select t7.*,t22.* from t22 left outer join t7 on (t22_1=s1);

Okay.

F041-04 RIGHT OUTER JOIN

Example: select t7.*,t22.* from t22 right outer join t7 on (t22_1=s1);

Fail. Syntax error.

F041-05 Outer joins can be nested

Example: select t7.*,t22.* from t22 left outer join t7 on (t22_1=s1) left outer join t23;

Okay.

F041-07 The inner table in a left or right outer join can also be used in an inner join

Example: select t7.* from t22 left outer join t7 on (t22_1=s1) inner join t22 on (t22_4=t22_5);

Okay. The query fails due to a syntax error but that's expectable.

F041-08 All comparison operators are supported (rather than just =)

Example: select * from t where 0=1 or 0>1 or 01;

Okay.

F051 Basic date and time

F051-01 DATE data type (including support of DATE literal)

Example: create table dates (s1 date);

Okay. (SQLite doesn't enforce valid dates or times, but we've already noted that.)

F051-02 TIME data type (including support of TIME literal)

Example: create table times (s1 time default time '1:2:3');

Fail. Syntax error.

F051-03 TIMESTAMP data type (including support of TIMESTAMP literal)

Example: create table timestamps (s1 timestamp);

Okay.

F051-04 Comparison predicate on DATE, TIME and TIMESTAMP data types

Example: select * from dates where s1 = s1;

Okay.

F051-05 Explicit CAST between date-time types and character string types

Example: select cast(s1 as varchar) from dates;

Okay.

F051-06 CURRENT_DATE

Example: select current_date from t;

Okay.

F051-07 CURRENT_TIME

Example: select * from t where current_time
Okay.

F051-08 LOCALTIME

Example: select localtime from t;

Fail. Syntax error.

F051-09 LOCALTIMESTAMP

Example: select localtimestamp from t;

Fail. Syntax error.

F081 UNION and EXCEPT in views

Example: create view vv as select * from t7 except select * from t15;

Okay.

F131 Grouped operations

F131-01 WHERE, GROUP BY, and HAVING clauses supported in queries with grouped views

Example: create view vv2 as select * from vv group by s1;

Okay.

F131-02 Multiple tables supported in queries with grouped views

Example: create view vv3 as select * from vv2,t30;

Okay.

F131-03 Set functions supported in queries with grouped views

Example: create view vv4 as select count(*) from vv2;

Okay.

F131-04 Subqueries with GROUP BY and HAVING clauses and grouped views

Example: create view vv5 as select count(*) from vv2 group by s1 having count(*) > 0;

Okay.

F181 Multiple module support

Fail. SQLite doesn't have modules.

F201 CAST function

Example: select cast(s1 as int) from t;

Okay.

F221 Explicit defaults

Example: update t set s1 = default;

Fail. Syntax error.

F261 CASE expression

F261-01 Simple CASE

Example: select case when 1 = 0 then 5 else 7 end from t;

Okay.

F261-02 Searched CASE

Example: select case 1 when 0 then 5 else 7 end from t;

Okay.

F261-03 NULLIF

Example: select nullif(s1,7) from t;

Okay.

F261-04 COALESCE

Example: select coalesce(s1,7) from t;

Okay.

F311 Schema definition statement

F311-01 CREATE SCHEMA

Fail. SQLite doesn't have schemas or databases.

F311-02 CREATE TABLE for persistent base tables

Fail. SQLite doesn't have CREATE TABLE inside CREATE SCHEMA.

F311-03 CREATE VIEW

Fail. SQLite doesn't have CREATE VIEW inside CREATE SCHEMA.

F311-04 CREATE VIEW: WITH CHECK OPTION

Fail. SQLite doesn't have CREATE VIEW inside CREATE SCHEMA.

F311-05 GRANT statement

Fail. SQLite doesn't have GRANT inside CREATE SCHEMA.

F471 Scalar subquery values

Example: select s1 from t where s1 = (select count(*) from t);

Okay.

F481 Expanded NULL Predicate

Example: select * from t where row(s1,s1) is not null;

Fail. Syntax error.

F812 Basic flagging

Fail. SQLite doesn't support any flagging

S011 Distinct types

Example: create type x as float;

Fail. SQLite doesn't support distinct types.

T321 Basic SQL-invoked routines

T321-01 User-defined functions with no overloading

Example: create function f () returns int return 5;

Fail. SQLite doesn't support user-defined functions.

T321-02 User-defined procedures with no overloading

Example: create procedure p () begin end;

Fail. SQLite doesn't support user-defined procedures.

T321-03 Function invocation

Example: select f(1) from t;

Fail. SQLite doesn't support user-defined functions.

T321-04 CALL statement.

Example: call p();

Fail. SQLite doesn't support user-defined procedures.

T321-05 RETURN statement.

Example: create function f() returns int return 5;

Fail. SQLite doesn't support user-defined functions.

T631 IN predicate with one list element

Example: select * from t where 1 in (1);

Okay.

The Final Score

Fail: 59

Okay: 75

Update 2016-06-26: Originally I counted 60 to 74, that was an error.

So SQLite could claim to support most of the core features of the current standard, according to this counting method, after taking into account all the caveats and disclaimers embedded in the description above.

I anticipate the question, "Will ocelotgui (the Ocelot Graphical User Interface for MySQL and MariaDB) support SQLite too?" and the answer is "I don't know." The project would only take two weeks, but I have no idea whether it's worth that much effort.

In the last while, I've concentrated on some ocelotgui bug fixes and on checking whether it runs on Windows as well as on Linux. It does, but only from source -- see the instructions at https://github.com/ocelot-inc/ocelotgui/blob/master/windows.txt.

PlanetMySQL Voting: Vote UP / Vote DOWN

Show more