T-SQL Quirks
Here are some surprises you may encounter when using RZSQL with T-SQL.
RZSQL fakes the IS and IS NOT operators
RZSQL uses IS and IS NOT to represent equality comparisons that treat NULL
as equal to itself. The naming of these operators is borrowed from SQLite.
T-SQL does not have general purpose binary operators suitable for this. You
can write expr IS NULL or expr IS NOT NULL in T-SQL, but these forms only
work for comparison with a literal NULL -- you can't, for example, compare two
columns this way.
When faced with a usage of IS or IS NOT that doesn't have a literal NULL
as its right-hand side, RZSQL uses this idiom for LeftSideExpr IS
RightSideExpr:
EXISTS(SELECT LeftSideExpr INTERSECT SELECT RightSideExpr);
Surprisingly, SQL Server seems to recognize this idiom and generates a pretty good query plan for it.
Play with the translation here.
RZSQL fakes the boolean data type
T-SQL does not have a boolean data type. It has a bit data type, which is
perfect for storing a boolean value, but does not behave as a boolean value.
For example, you cannot use a bit column un-adorned within a WHERE clause, as in:
-- this is not valid T-SQL
SELECT * FROM SomeTable WHERE SomeBitColumn
All SQL dialects must include boolean expressions, since SQL is near worthless
without its WHERE clause. But in T-SQL, those boolean expressions are only
allowed within the clauses that require them, such as CASE, WHERE, and HAVING.
You cannot evaluate a boolean expression and get a scalar value out:
-- this is not valid T-SQL either
SELECT (Column1 < Column2) AS IsLessThan FROM SomeTable
RZSQL has a boolean data type and for consistency's sake it's nice to be able to
pretend it works normally, regardless of backend. To facilitate this, the T-SQL
backend for RZSQL fakes the existence of a boolean data type by inserting <> 0
whenever a "fake boolean" is used in a boolean clause:
SELECT * FROM SomeTable WHERE (SomeBitColumn<>0)
Conversely, it adds a CASE expression whenever a boolean expression such as x
< y is used where a scalar value is needed:
SELECT
(CAST((CASE WHEN (Column1 < Column2) THEN 1 ELSE 0 END) AS BIT)) AS IsLessThan
FROM SomeTable
See the translation for yourself here.
LIMIT/OFFSET is not the same as SELECT TOP
If you're familiar with T-SQL, you probably recognize RZSQL's LIMIT clause as
being like T-SQL's SELECT TOP:
-- RZSQL
SELECT * FROM USERS LIMIT 1;
-- T-SQL
SELECT TOP 1 * FROM Users;
In simple cases this is true. They are equivalent. However, the LIMIT clause
has an optional OFFSET, which TOP does not. If an OFFSET is supplied,
LIMIT translates to a less-used, newer piece of T-SQL syntax:
-- RZSQL
SELECT * FROM Example LIMIT 1 OFFSET 1;
-- T-SQL
SELECT * FROM Example OFFSET 1 ROWS FETCH NEXT 1 ROWS ONLY;
Is that syntax beautiful or what? You can almost hear the robotic voice.
Sometimes, the OFFSET/FETCH syntax must be used even if there is no LIMIT clause.
This is because of a different in the scope of T-SQL's SELECT TOP and RZSQL's LIMIT.
When tables are smushed together via a
compound-expr, LIMIT cuts down the total
result set. SELECT TOP only trims down the rows from the SELECT clause it
was applied to.
So, a query that combines multiple queries with e.g. UNION ALL before limiting
the reuslts will always be translated to use an OFFSET/FETCH clause in T-SQL.
You can explore how the LIMIT clause is translated
here.
Must drop default before dropping column
T-SQL models default values as constraints, and refuses to let you drop a column while it has constraints referencing it, even if the constraints will become completely pointless once the column is gone.
Therefore, you must ALTER TABLE DROP DEFAULT FOR ColumnName before you ALTER
TABLE DROP COLUMN ColumnName, if the column has a default value.
You'll get informed of this at compile time.
No ALTER TABLE RENAME TO
You'll get an exception at compile time if you use this statement.
This clause could perhaps be translated to sp_rename, but currently is just
prohibited outright. If you need it, try using a vendor statement with an
IMAGINE clause that claims to drop and recreate the table (while actually
running sp_rename and whatever else you need).
No bitwise shift operators
T-SQL supports bitwise & and |, but no left or right shifts. You'll get an
exception at compile time if you use the << or >> operators.