rspec/rules/S4104/tsql/rule.adoc
Fred Tingaud 16f6c0aecf
Inline adoc when include has no additional value (#1940)
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.
2023-05-25 14:18:12 +02:00

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[]