
Inline adoc files when they are included exactly once. Also fix language tags because this inlining gives us better information on what language the code is written in.
109 lines
2.4 KiB
Plaintext
109 lines
2.4 KiB
Plaintext
== Why is this an issue?
|
|
|
|
``++COALESCE++`` and ``++IIF++`` (which evaluate to ``++CASE++`` expressions under the covers), as well as ``++CASE++`` input expressions should not be used with subqueries because the subquery will be evaluated once for each option in the expression, and each evaluation could return different results depending on the isolation level. To ensure consistent results, use the ``++SNAPSHOT ISOLATION++`` isolation level. To ensure consistent results _and_ better performance, move the subquery out of the expression.
|
|
|
|
|
|
Note it is also an option to replace ``++COALESCE++`` with ``++ISNULL++``.
|
|
|
|
|
|
=== Noncompliant code example
|
|
|
|
[source,sql]
|
|
----
|
|
...
|
|
COALESCE((SELECT a FROM b WHERE c) , 1) -- Noncompliant
|
|
...
|
|
----
|
|
|
|
[source,sql]
|
|
----
|
|
...
|
|
CASE
|
|
WHEN (SELECT COUNT(*) FROM A) > 0 THEN (SELECT COUNT(*) FROM A) + 42
|
|
...
|
|
ELSE otherExpression
|
|
END
|
|
...
|
|
----
|
|
|
|
|
|
=== Compliant solution
|
|
|
|
[source,sql]
|
|
----
|
|
SET @a = SELECT a FROM b WHERE c
|
|
...
|
|
COALESCE(@a, 1)
|
|
...
|
|
----
|
|
or
|
|
|
|
[source,sql]
|
|
----
|
|
SET TRANSACTION ISOLATION LEVEL SNAPSHOT
|
|
BEGIN TRANSACTION
|
|
...
|
|
COALESCE((SELECT a FROM b WHERE c) , 1)
|
|
...
|
|
----
|
|
|
|
[source,sql]
|
|
----
|
|
...
|
|
|
|
SET @a = SELECT COUNT(*) FROM A
|
|
|
|
CASE
|
|
WHEN @a > 0 THEN @a + 42
|
|
...
|
|
ELSE otherExpression
|
|
END
|
|
...
|
|
----
|
|
|
|
|
|
ifdef::env-github,rspecator-view[]
|
|
|
|
'''
|
|
== Implementation Specification
|
|
(visible only on this page)
|
|
|
|
=== Message
|
|
|
|
Either set use the "SNAPSHOT ISOLATION" level or rewrite this statement to eliminate "xxx".
|
|
|
|
|
|
=== Highlighting
|
|
|
|
``++select++``
|
|
|
|
|
|
'''
|
|
== Comments And Links
|
|
(visible only on this page)
|
|
|
|
=== on 20 Jul 2017, 16:09:19 Pierre-Yves Nicolas wrote:
|
|
The title should be changed: subqueries are expressions, and the problem described in this RSPEC only applies to COALESCE, IFF and CASE.
|
|
|
|
|
|
Also, if my understanding is correct:
|
|
|
|
----
|
|
CASE (select...) WHEN... END -- Noncompliant
|
|
CASE... WHEN (select...)... END -- Compliant
|
|
----
|
|
|
|
|
|
=== on 20 Jul 2017, 16:18:45 Ann Campbell wrote:
|
|
See what you think [~pierre-yves.nicolas]
|
|
|
|
=== on 20 Jul 2017, 16:40:33 Pierre-Yves Nicolas wrote:
|
|
Looks good.
|
|
|
|
Nitpicking: it's fine to have a subquery inside a ``++WHEN++`` inside a ``++CASE++``, so we should maybe change "as well as CASE expressions" to "as well as expressions immediately following the CASE keyword".
|
|
|
|
=== on 20 Jul 2017, 17:04:30 Ann Campbell wrote:
|
|
\[~pierre-yves.nicolas] I've updated to "input expression" based on https://docs.microsoft.com/en-us/sql/t-sql/language-elements/case-transact-sql[this doc].
|
|
|
|
endif::env-github,rspecator-view[]
|