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.

results matching ""

    No results matching ""