SQL reserved words – An empirical list
modern-sql.com
modern-sql.com
[1] I used to prefer plural names, but now I favor singular names because no naming headaches with the plural intricacies of the English language.
("user" is what got me in the habit of doing this unconditionally, to the point where SQL with bare table/column names looks weird to me now.)
Oh and yeah, every database brings its own opinion on what [quoting] `should` "look" 'like'.
Well yes hence “use quoted identifiers for maximum compatibility”. That does not mean “use quoted identifiers except when you don’t want to”.
I probably should have gone with accounts and had a species column.
Just kidding. Then you'd eventually need extraterrestrials, sentient_ai, ghosts, and all kinds of extras.
CREATE TABLE "user" (
id int PRIMARY KEY,
name varchar(50) NOT NULL
);
In fact, in this respect, SQL is much better than most languages with their `clazz` and `klass` and `func`.This solution was devised as a means to add keywords to new editions of the language without breaking code written in the old edition that named this stuff the same as the keyword (and with full interoperability between code from new editions and old editions)
So if some function in some Rust 2015 library was named async (a new keyword introduced in Rust 2018), you can call it like r#async() in newer versions
val `val` = 1Such macros can be defined by libraries or the end user to provide special behavior.
CREATE USER user_name
[
{ FOR | FROM } LOGIN login_name
]
[ WITH <limited_options_list> [ ,... ] ]
[ ; ]As for how to name the "user" table, I've used "account". User is a human not a piece of data, Account is the data I have about their association with my service.
Of surrounding by square brackets in SQL Server, like [so] instead of like "so", which despite being non-standard is more commonly used in the MS SQL world because its behaviour is much more consistent than quotes in that environment.
Quoted (rather than bracketed) identifiers are supported but it depends upon a setting which may vary per DB or procedure. It is common to see the option ON these days a some features¹ depend upon it, and many tools like MS's SSMS default it to ON, but this can not at all be relied upon. See https://learn.microsoft.com/en-us/sql/t-sql/statements/set-q...
--
[1] From the documentation: “SET QUOTED_IDENTIFIER must be ON when you are creating or changing indexes on computed columns or indexed views. If SET QUOTED_IDENTIFIER is OFF, then CREATE, UPDATE, INSERT, and DELETE statements will fail on tables with indexes on computed columns, or tables with indexed views.”
I'd like Postgres more (and really want to) if they would at least implement more basic stuff like SQL:2011 and/or there was a good hosted deploy story - RDS/Aurora is fairly complex.
https://learn.microsoft.com/en-us/sql/tools/sqlpackage/sqlpa...
The APIs were historically part of Visual Studio, and only split out into dacfx recently.
Someone braver than me could consider automated deployment from github actions etc.
The hard part is that a lot of database schema changes cause data truncation (e.g. reducing the size of a column or re-ordering columns).
You still need someone to review the generated code if it throws an error for potential data loss.
Yeah, exactly what I meant by the terraform-like plan/apply stages. You generate the change script and save it as your "plan", and then have an apply step that takes a backup and runs the script.
Also, which features in particular are you missing in PostgreSQL? Merge was added with PostgreSQL 15 a year ago: https://modern-sql.com/caniuse/merge
100% agreed. It's remarkable how Datomic also arrived on the scene in the same era (2012) but actually managed to solve a lot of these hard issues of immutable versioning + schema evolution via a clean EAV-based information model and an emphasis on accrete-only schema changes.
I'm a big fan of your work by the way :)
I find the temporal table stuff really useful and they drastically simplify a number of requirements, so it's annoying that the only non-proprietary DB that supports it is maria.
https://en.wikipedia.org/wiki/SQL/PSM
This is so pervasive in both free and commercial databases, that it is a gaping hole in SQL Server where obvious functionality should be.
I have thousands of lines of this stuff that will never see the light of day in a conversion because of Sybase Transact-SQL.
Why is Microsoft addicted to this very much not standard language, that they did not even originate?
While not the shit-show of bugs it was upon introduction in SQL Server 2008, there are still reasons to be careful with MERGE in SQL Server: it can still deadlock with itself in some circumstances, has issues with filtered indexes, can cause problems with CDC (wrong operation(s) get logged), …
(I actually like SQL Server, but the implementation of MERGE found there-in is certainly not one of the things I like about it!)
Can’t comment on Sybase. Didn’t need any other platforms.
?
INSERT INTO [FROM] ([SELECT], [WHERE], [EQUALS]) VALUES( 'WHY YES', 'IT DOES', 'WORK')
WITH [WITH] AS (
SELECT [AS], [IN], [ON]
FROM [UNION]
WHERE [AND] = [OR]
),
[OUTER] AS (
SELECT [LEFT], [RIGHT], [FULL]
FROM [CROSS]
WHERE [INNER] = [OUTER]
),
[GROUP] AS (
SELECT COUNT(*) AS [HAVING]
FROM [ORDER]
GROUP BY [GROUP]
HAVING COUNT(*) > 1
)
SELECT
[WITH].[AS],
[OUTER].[LEFT],
[GROUP].[HAVING]
FROM
[WITH]
JOIN
[OUTER]
ON
[WITH].[IN] = [OUTER].[RIGHT]
LEFT JOIN
[GROUP]
ON
[WITH].[ON] = [GROUP].[HAVING]
WHERE
[WITH].[AS] = [OUTER].[LEFT]
AND
([GROUP].[HAVING] IS NULL OR [GROUP].[HAVING] > 1)
ORDER BY
[WITH].[AS] ASC;implementing algorithms in SQL really made my intuition for SQL skyrocket, to the point where no tasks in my day to day data engineering role were very challenging - at least not in terms of dealing with crazy joins and subqueries and such.
I miss SQL now days (as an appsec dev). Currently, I'm learning Hoon, which is too intuitive to really replace SQL as a language for doing toy problems while having to think wierd.
You remind me I need to finish my hunt the wumpus implementation. (sqlite has an easy way to get user input, mid query...)
I'll admit that I'm not an expert here but to my eye it's a combination of bare words and cases where the position might be amgiuous, combined with the range of dialects where your reserved words could even change in the future. `select distinct` could be `select [distinct]` or just `select distinct`. Compare to say C where `sometype somebareword` isn't ambiguous because `sometype` is always a language keyword. But wait you say, with typedefs sometype could well be a `typedef stuct somebareword! Yep, it's a problem here too and I've been lying all along.
So that's some rambling but I think you're right, it's just a problem in SQL because of the range of dialects and the fact that they can change out from under you.
Not having keywords at all is cheating :)
Or, for Common Lisp at least, perhaps we can say that (,), #, ;, ", `,', :, commas, whitespace, and numbers are actually the keywords, since most other ASCII chars are valid identifiers but these aren't (so you can have a variable named = or ?, but you can't have a variable named # or 1. And in that case, CL also mixes up "keywords" and identifiers just like everyone else :) .
> Compare to say C where `sometype somebareword` isn't ambiguous because `sometype` is always a language keyword. But wait you say, with typedefs sometype could well be a `typedef stuct somebareword! Yep, it's a problem here too and I've been lying all along.
Even without typedefs, you have a problem more closely related to "select x" VS "select distinct x" - you can have "long x;" or "long double x;".
Either way, yes, I think we agree - there's a difference in quantity and stability of keywords with SQL, but not much else.
MySQL's SQL is the only language I use where I regularly trip on reserved keywords, super annoying. Not sure off the top of my head if there's some better design to fix that short of namespacing every reserved keyword. In some cases you can do `` to get around it but better to avoid them altogether.
From the wording of TFA, it probably only lists reserved keywords.
create table type (
type integer
);
insert into type (type) values (1), (2);
select type from type;
works perfectly fine in all of sqlite, postgres, mysql, and sql server (at least according to onecompiler.com).To use the type example you provided, I’ve seen that example break syntax highlighting and ORMs where you need special quoting to make it work.
Can you tell me: what kind of identifier is it (view name, function name) and which SQL context it causes problems (select list, create/drop statement, ...) and which system has problems with it. Thx.
I also find their documentation on this sort of thing to be far too sprawled to be easily accessible, makes it quite hard to prepare for this sort of thing if you're not particularly expert when it comes to database administration.
[0]: https://github.com/sqlfluff/sqlfluff/blob/main/src/sqlfluff/... [1]: https://github.com/sqlfluff/sqlfluff/blob/main/src/sqlfluff/... [2]: https://github.com/sqlfluff/sqlfluff/blob/main/src/sqlfluff/...
SELECT SELECT FROM FROM
is a valid query. create table from (select UInt8, where UInt8) engine = MergeTree() order by tuple();
insert into from values (1, 1), (2, 1), (3, 0), (4, 0), (5, 1);
select select from from where where;
select select from from where where is a really lovely query.Do yourself a favor and pick up some books about SQL by Joe Celko's SQL Puzzles and Answers. If you follow it, you will learn how to accomplish various queries while having restrictions on dialects or whatever. It's a real mind-expander. I found myself doing in SQLite things I hadn't thought possible for that set of keywords.
I'd recommend digging into PostgreSQL as well, since it's "larger" than SQLite and will expose you to a bunch more concepts.
If you're familiar with both SQLite and PostgreSQL you should find other dialects very easy to pick up when you need them.
1. Write the SQL that I think should mostly work
2. Try to run it
3. Fix errors with the help of docs, Stack Overflow, and now generative AI
4. Subconsciously learn whatever dialect this is to improve my performance on Step 1
This sort of an approach often causes there to be hidden bugs, which do not generate errors now, but will cause some problem down the line.
It also has a tendency to lead to cargo cult programming (https://en.wikipedia.org/wiki/Cargo_cult_programming), which is less immediately problematic, but is still not great, especially for whoever needs to maintain that code.
Which one should be your core one depends on what projects you wish to work on. My DayJob is an MS shop to SQL Server's TSQL is my area of expertise, but I know more-or-less what isn't supported or is handled differently in other common places (core postgres, mysql/mariadb, sqlite). In some places you may end up being more completely fluent in multiple rather than just one. The key is understanding the concepts (set based operations rather than thinking procedurally, recursive queries, window functions, how query planners commonly work so you can optimise for them) rather than specific syntax which is always easy to lookup.
The longer answer is that some RBDMS adhere closer to the standard than others. Generally the more open source and more long lived a platform is, the closer to the standard it can be. However, even an RDBMS like MSSqlServer isn't that far off from it, and while it may have things it supports that are outside of that standard, it will still support ANSI SQL (i.e. `ISNULL` vs `COALESCE`)
If you're looking for learning SQL that you can likely use in a wide number of places, I'd steer away from Oracle and DB2. Both are fairly proprietary, in my experience, and feel like writing in a different language that looks like SQL, but has a different set of rules and constraints.
I do think that, as general learning experience, working with PostgreSQL is a good starting place because of the good degree of SQL standard compliance. Get those basics down and the less standards compliant vendors become more accessible.
After that it depends what kinda of companies you'd want to work for. Enterprises deal much in MSSQL and Oracle. Start-uppy kinds of companies you're looking at PostgreSQL or MySQL... Or something not RDBMS at all. There are many generalizations that can be made but these are a few hand-wavy examples I would make.
It's clever, giving SQLite a lot of power in limited code, important in its conventional application in embedded use cases where fixed costs like code object size and starting database heap size are pretty constrained, and databases tend to be small...but, nevertheless, it's in its own world, there.
SQLite is fine. The biggest issue to be aware of with SQLite is that SQLite's type affinity system is completely different from how other SQL RDBMSs function. The norm is for columns to have much more rigid data typing.
Other databases all had wonky left join syntax before the SQL92 standard - every attempt should be made to avoid archaic syntax if possible. SQLite itself lacked right join until recently.
Procedural SQL comes in two common varieties - ANSI SQL/PSM (strongly influenced by Oracle), and Transact-SQL (that is only found on Sybase and Microsoft SQL Server). Choose your investment here carefully.
I'd go for CHECK constraints first: https://www.sqlite.org/lang_createtable.html#ckconst
> Procedural SQL [...] Choose your investment here carefully.
I think that the demand for procedual code has dropped drastically in the past decades as the "normal" SQL can solve so many more things with window functions, recursion, and so forth. So I'd say: Yes, choose your investment wisely and stay away from procedural SQL as long as possible.
I have thousands of lines of PL/SQL that originated in the days of PowerBuilder that are now serviced by .NET; a decade from now could be totally different.
SQLite appears to use a (very small) subset of PSM for triggers.
All charts on modern-sql.com are backed by tests. I also keep them up-to-date by running them for new releases when they appear.
The SQL standard specifies a large number of keywords which may not be used as the names of tables, indices, columns, databases, user-defined functions, collations, virtual table modules, or any other named object. The list of keywords is so long that few people can remember them all. For most SQL code, your safest bet is to never use any English language word as the name of a user-defined object.
https://www.sqlite.org/lang_keywords.htmlAnd obviously this is only for maximally portable SQL, postgres has a comparative table, which demonstrates that many of SQL's reserved keywords are non-reserved in postgres-sql: https://www.postgresql.org/docs/current/sql-keywords-appendi...
I loathe plurality in table names because it's hard for ESL developers due to the plethora of irregular pluralities (like the word pluralities) in english. If object/entity names and table names are both singular you can do a lot of stuff on autopilot.
Anywho, I agree, you see:
"It puts the lotion in the basket"
See? Not a plural in sight!
As pointed out by other replies to your comment. Abbreviations can lead to similar problems even with native speakers.
No. It just requires they be quoted.
---
The SQL standard forbids certain "regular identifiers," however it places no such restriction of "delimited identifiers." I.e. use quotes.