فهرست مقاله
فرض کنید فهرستی از حسگرهای یک آزمایشگاهِ ساختگی داریم و میخواهیم حسگرهای فاقد رکوردِ کالیبراسیون را پیدا کنیم. واردکنندهٔ داده گاهی رکوردی میآورد که هنوز به حسگری نسبت داده نشده است؛ ستونِ شناسهٔ حسگر در آن ردیف NULL است. پرسوجوی ظاهراً سادهٔ NOT IN ممکن است پس از اضافهشدن همین ردیف، هیچ حسگرِ بیکالیبراسیونی نشان ندهد. این اتفاق، حذفِ حسگر یا اثباتِ کالیبرهبودنِ همهٔ دستگاهها نیست؛ معنای شرطِ انتخاب را اشتباه پرسیدهایم.
۱. NULL را شناسهٔ یک حسگرِ دیگر نگیریم

در شاهد دستی، شناسههای حسگر یک، دو و سهاند. جدولِ فرزند دو ردیف دارد: یک رکورد به حسگر یک وصل شده و شناسهٔ حسگرِ رکورد دیگر نامعلوم است. پرسشِ کاری ما این است: «کدام شناسهٔ معلوم، هیچ فرزندِ دارای شناسهٔ برابر ندارد؟» پاسخِ مورد انتظار دو و سه است. خودِ NULL یک شناسهٔ اضافه، مقدارِ صفر یا شمارهٔ دستگاهی بیرون از فهرست نیست.
دامنهٔ برنامه عمداً کوچک است. ورودیِ سمت حسگر، tuple دقیقِ حداکثر هشت شناسهٔ صحیحِ متمایز از صفر تا هفت است و NULL نمیپذیرد. ورودیِ سمت کالیبراسیون، tuple دقیقِ حداکثر هشت مقدار از همین شناسهها یا None است؛ تکرارِ رکورد مجاز است. این اعداد، شناسههای قراردادیاند و واحد فیزیکی ندارند. برنامه هیچ ولتاژ، ضریب تصحیح یا دقتِ ابزار اندازه نمیگیرد.
این تفکیک را با درس سطحِ رکورد و NULL در JOIN مقایسه کنید. در آنجا، مقدارِ نامعلومِ یک نمونه با نبودنِ خودِ نمونه فرق داشت. اینجا وجودِ یک ردیفِ فرزند نیز به معنی وجودِ تطبیق برای هر حسگر نیست. فقط وقتی برابریِ شناسهٔ معلوم برقرار شود، شاهدِ اتصال به همان حسگر پیدا کردهایم.
۲. NOT IN به نابرابریِ قطعی نیاز دارد

ماتریس کامل IN و NOT IN در مرجع SQLite حالتِ مجموعهٔ خالی، تطبیقِ موجود و مقدارِ تهی را جدا میکند. برای حسگر دو، برابری با شناسهٔ یک نادرست است، اما برابری با NULL نامعلوم میماند. پس عضویت در مجموعهٔ یک و NULL، پاسخِ نامعلوم دارد؛ نقیضِ نامعلوم نیز همچنان نامعلوم است، نه درست.
WHERE فقط ردیفی را نگه میدارد که شرطش درست باشد. هم پاسخِ نادرست و هم پاسخِ نامعلوم از خروجی کنار میروند، ولی این دو ارزش یکسان نیستند. به همین دلیل گزارش فقط شناسههای انتخابشده را نشان نمیدهد؛ نتیجهٔ هر شرط را نیز با برچسبهای روشنِ true، false و unknown ثبت میکند. تبدیل زودهنگامِ None به bool پایتون، همین تفاوتِ آموزشی را پنهان میکرد.
وجود NULL همیشه نتیجهٔ IN را نامعلوم نمیکند. حسگر یک با رکوردِ معلومِ یک تطبیق دارد؛ IN برای آن درست و NOT IN نادرست است، حتی اگر کنار آن ردیف، چند NULL هم باشد. در مقابل، زیرپرسوجوی خالی، هیچ مانعِ برابری ندارد و NOT IN برای شناسههای مجازِ این درس درست میشود. «هیچ ردیفی نیست» با «یک ردیفِ دارای مقدارِ نامعلوم هست» دو حالتِ متفاوت است.
۳. NOT EXISTS نبودِ تطبیق را میپرسد

در نسخهٔ دوم، شرطِ برابریِ شناسه در زیرپرسوجوی همبسته قرار میگیرد. برای هر حسگر میپرسیم آیا ردیفی از کالیبراسیون هست که شناسهاش با این حسگر برابر باشد. مقایسهٔ NULL با شناسهٔ معلوم، آن ردیفِ بیصاحب را به شاهدِ برابری تبدیل نمیکند. NOT EXISTS وقتی درست است که هیچ ردیفِ پذیرفتهشدهای از این زیرپرسوجو برنگردد.
بخش زیرپرسوجوهای مرجع رسمی PostgreSQL نیز تفاوتِ وجودِ ردیف و عضویتِ دارای NULL را توضیح میدهد. این سند، مرجعِ دومِ معنای SQL است؛ کدِ حاضر PostgreSQL را اجرا نمیکند. همچنین EXISTS ذاتاً «ردیفهای NULL را نادیده نمیگیرد»: EXISTS روی زیرپرسوجویی که یک ردیفِ NULL برگرداند، درست است. در مثال ما، شرطِ برابری تعیین میکند کدام ردیف اصلاً برگردد.
راهِ دیگر، کنارگذاشتنِ رکوردهای بیصاحب از سمت راستِ NOT IN است. برنامه این نسخه را هم گزارش میکند تا فرضِ لازم دیده شود. در دامنهٔ حاضر، شناسههای سمت چپ غیرتهیاند و پرسش دربارهٔ نبودِ برابریِ معمولی است؛ با حذفِ NULLهای سمت راست، دو انتخاب هممعنا میشوند. این جمله، مجوزِ بازنویسیِ هر NOT IN دلخواه نیست؛ ستونِ چپِ nullable، مقایسهٔ چندستونی یا سیاستِ دیگری برای برابری، تحلیلِ جدا میخواهد.
۴. آزمایشِ پایتون و مرجعِ سهارزشیِ مستقل

تابع missing_calibration_report پس از بررسیِ کاملِ ورودیها، یک پایگاهِ حافظهایِ خصوصی میسازد. نام جدولها و متنِ دستورها ثابتاند؛ مقدارها با جاینگهدار وارد میشوند. یک ستونِ ترتیبِ صریح، ترتیبِ ورودیِ حسگرها را در گزارش حفظ میکند؛ ترتیبِ ذخیرهسازی را قراردادِ خروجی فرض نکردهایم. اتصال در finally بسته میشود و هیچ فایلِ موجود یا سرویسی باز نمیشود.
مرجعِ مستقل، SQL اجرا نمیکند. برای NOT IN، نابرابری با هر مقدار را در جدولِ صریحِ منطقِ سهارزشی ترکیب میکند؛ نابرابری با None نامعلوم است، نه نتیجهٔ عملگرِ معمولیِ پایتون. برای NOT EXISTS، فقط دنبال شاهدِ عددیِ برابری میگردد. جوابِ مورد انتظار از نتیجهٔ یک پرسوجوی دیگر یا از شاخههای تابعِ اصلی ساخته نشده است.
"""Scalar NULL anti-membership, fixed private in-memory SQLite experiment."""
from dataclasses import FrozenInstanceError, asdict, dataclass
import itertools
import json
import platform
import sqlite3
import sys
MAX_ROWS = 8
MAX_ID = 7
TRUTHS = """SELECT s.sensor_id,
s.sensor_id IN (SELECT c.sensor_id FROM calibration AS c),
s.sensor_id NOT IN (SELECT c.sensor_id FROM calibration AS c),
EXISTS(SELECT 1 FROM calibration AS c WHERE c.sensor_id=s.sensor_id),
NOT EXISTS(SELECT 1 FROM calibration AS c WHERE c.sensor_id=s.sensor_id)
FROM sensor AS s ORDER BY s.ordinal"""
NOT_IN = """SELECT s.sensor_id FROM sensor AS s
WHERE s.sensor_id NOT IN (SELECT c.sensor_id FROM calibration AS c)
ORDER BY s.ordinal"""
NOT_EXISTS = """SELECT s.sensor_id FROM sensor AS s
WHERE NOT EXISTS(SELECT 1 FROM calibration AS c WHERE c.sensor_id=s.sensor_id)
ORDER BY s.ordinal"""
FILTERED_NOT_IN = """SELECT s.sensor_id FROM sensor AS s
WHERE s.sensor_id NOT IN
(SELECT c.sensor_id FROM calibration AS c WHERE c.sensor_id IS NOT NULL)
ORDER BY s.ordinal"""
@dataclass(frozen=True)
class MissingReport:
# Rows: ID, IN, NOT IN, correlated EXISTS, correlated NOT EXISTS.
truth_rows: tuple
not_in_selected: tuple
not_exists_selected: tuple
filtered_not_in_selected: tuple
def validate_inputs(sensor_ids, calibration_sensor_ids):
"""Whole finite input validation precedes any connection or SQL call."""
if type(sensor_ids) is not tuple or type(calibration_sensor_ids) is not tuple:
raise TypeError("both collections must be exact materialized tuples")
if len(sensor_ids) > MAX_ROWS or len(calibration_sensor_ids) > MAX_ROWS:
raise ValueError("at most eight entries per input")
seen = set()
for identifier in sensor_ids:
if type(identifier) is not int:
raise TypeError("left IDs are exact non-null ints, excluding bool")
if not 0 <= identifier <= MAX_ID or identifier in seen:
raise ValueError("left IDs must be distinct in 0..7")
seen.add(identifier)
for identifier in calibration_sensor_ids:
if identifier is None:
continue
if type(identifier) is not int:
raise TypeError("child IDs are exact ints or None")
if not 0 <= identifier <= MAX_ID:
raise ValueError("child IDs must be in 0..7 or None")
def truth_word(value):
if value is None:
return "unknown"
if type(value) is not int or value not in (0, 1):
raise AssertionError("unexpected SQLite predicate representation")
return "true" if value == 1 else "false"
def missing_calibration_report(sensor_ids, calibration_sensor_ids):
"""Compare fixed predicates for supplied non-null scalar left IDs.
A NULL child ID denotes an unassigned synthetic child record. It is not
a measurement, zero ID, authenticated identity or database-format error.
No arbitrary SQL, database connection or schema is accepted by this API.
"""
validate_inputs(sensor_ids, calibration_sensor_ids)
connection = sqlite3.connect(":memory:", autocommit=True)
try:
connection.execute("CREATE TABLE sensor(ordinal INTEGER PRIMARY KEY,"
"sensor_id INTEGER NOT NULL UNIQUE)")
connection.execute("CREATE TABLE calibration(sensor_id INTEGER)")
connection.executemany("INSERT INTO sensor VALUES(?,?)",
tuple(enumerate(sensor_ids)))
connection.executemany("INSERT INTO calibration VALUES(?)",
tuple((identifier,) for identifier in calibration_sensor_ids))
truth_rows = tuple((row[0],) + tuple(truth_word(v) for v in row[1:])
for row in connection.execute(TRUTHS))
selected = []
for statement in (NOT_IN, NOT_EXISTS, FILTERED_NOT_IN):
selected.append(tuple(row[0] for row in connection.execute(statement)))
return MissingReport(truth_rows, *selected)
finally:
connection.close()
AND = {
("true", "true"): "true", ("true", "false"): "false",
("true", "unknown"): "unknown", ("false", "true"): "false",
("false", "false"): "false", ("false", "unknown"): "false",
("unknown", "true"): "unknown", ("unknown", "false"): "false",
("unknown", "unknown"): "unknown",
}
NEGATE = {"true": "false", "false": "true", "unknown": "unknown"}
def truth_table_oracle(sensor_ids, calibration_sensor_ids):
"""Independent valid-input value fold: no SQL, DB or production helper.
NOT IN is the conjunction of scalar inequalities in three-valued logic.
Correlated existence instead asks whether a concrete equality witness
occurs. It does not interpret Python's None != integer as SQL truth.
"""
rows = []
anti_members = []
anti_witnesses = []
for identifier in sensor_ids:
conjunction = "true"
for child in calibration_sensor_ids:
unequal = ("unknown" if child is None else
"false" if identifier == child else "true")
conjunction = AND[(conjunction, unequal)]
witness = next((i for i, child in enumerate(calibration_sensor_ids)
if child is not None and child == identifier), None)
exists = "true" if witness is not None else "false"
rows.append((identifier, NEGATE[conjunction], conjunction,
exists, NEGATE[exists]))
if conjunction == "true":
anti_members.append(identifier)
if witness is None:
anti_witnesses.append(identifier)
return MissingReport(tuple(rows), tuple(anti_members),
tuple(anti_witnesses), tuple(anti_witnesses))
def raises(expected, function, *args):
try:
function(*args)
except expected:
return True
return False
def invalid_input_controls():
class IntSubclass(int):
pass
class TupleSubclass(tuple):
pass
consumed = []
def lazy():
consumed.append(True)
yield 1
bad_types = [([], ()), ((), []), (None, ()), ((), None),
(TupleSubclass(), ()), ((), TupleSubclass()),
(lazy(), ()), ((None,), ()), ((True,), ()),
((1.0,), ()), (("1",), ()), ((IntSubclass(1),), ()),
((1,), (True,)), ((1,), (1.0,)), ((1,), ("1",)),
((1,), (IntSubclass(1),)), ((1,), (0, 2, True))]
bad_values = [((-1,), ()), ((8,), ()), ((1, 1), ()),
((), (-1,)), ((), (8,)), ((1,), (0, 2, 8)),
(tuple(range(9)), ()), ((), (None,) * 9)]
attempted = []
actual_connect = sqlite3.connect
def forbidden_connect(*args, **kwargs):
attempted.append((args, kwargs))
raise AssertionError("connection opened before whole validation")
try:
sqlite3.connect = forbidden_connect
types_ok = all(raises(TypeError, missing_calibration_report, *pair)
for pair in bad_types)
values_ok = all(raises(ValueError, missing_calibration_report, *pair)
for pair in bad_values)
finally:
sqlite3.connect = actual_connect
return {"passed": types_ok and values_ok and not attempted and not consumed,
"invalid_type_profiles": len(bad_types),
"invalid_value_or_size_profiles": len(bad_values),
"connection_attempts": len(attempted), "generator_consumed": bool(consumed)}
def report_and_cleanup_controls():
actual_connect = sqlite3.connect
closed = []
inject = [False]
sentinel = RuntimeError("expected injected predicate read failure")
class Tracked:
def __init__(self, connection):
self.connection = connection
def execute(self, statement, *args):
if inject[0] and statement == TRUTHS:
raise sentinel
return self.connection.execute(statement, *args)
def executemany(self, *args):
return self.connection.executemany(*args)
def close(self):
closed.append(True)
self.connection.close()
def connect(*args, **kwargs):
return Tracked(actual_connect(*args, **kwargs))
left, right = (3, 1, 2), (1, None)
try:
sqlite3.connect = connect
first = missing_calibration_report(left, right)
second = missing_calibration_report(left, right)
empty = missing_calibration_report((), ())
inject[0] = True
caught = None
try:
missing_calibration_report((1,), (None,))
except RuntimeError as error:
caught = error
finally:
sqlite3.connect = actual_connect
immutable = raises(FrozenInstanceError, setattr, first, "truth_rows", ())
def mutate_row():
first.truth_rows[0] = (1,)
nested_immutable = raises(TypeError, mutate_row)
return {"passed": first == second and immutable and nested_immutable and
empty == MissingReport((), (), (), ()) and left == (3, 1, 2) and
right == (1, None) and caught is sentinel and closed == [True] * 4,
"actual_connections_closed": len(closed),
"expected_injected_error_identity_preserved": caught is sentinel}
def run_example():
checks = {}
def check(name, result):
if type(result) is not bool or not result:
raise AssertionError(name)
checks[name] = result
manual = missing_calibration_report((1, 2, 3), (1, None))
hand = MissingReport(((1, "true", "false", "true", "false"),
(2, "unknown", "unknown", "false", "true"),
(3, "unknown", "unknown", "false", "true")),
(), (2, 3), (2, 3))
check("manual_unassigned_child_changes_anti_membership", manual == hand)
matched = missing_calibration_report((1,), (None, 1, None))
check("concrete_match_wins_over_unknown_alternatives",
matched.truth_rows == ((1, "true", "false", "true", "false"),))
empty_rhs = missing_calibration_report((1, 2), ())
check("empty_child_subquery_has_true_anti_membership",
empty_rhs.truth_rows == ((1, "false", "true", "false", "true"),
(2, "false", "true", "false", "true")))
null_rhs = missing_calibration_report((1, 2), (None,))
check("NULL_only_child_subquery_differs_from_empty",
null_rhs.not_in_selected == () and null_rhs.not_exists_selected == (1, 2)
and all(row[1:3] == ("unknown", "unknown") for row in null_rhs.truth_rows))
check("duplicate_children_and_NULLs_are_semantically_redundant",
missing_calibration_report((1, 2, 3), (1, 1, None, None)) == manual)
check("child_order_does_not_change_scalar_predicates",
all(missing_calibration_report((1, 2, 3), child) == manual
for child in ((None, 1), (1, None), (None, 1, None))))
ordered = missing_calibration_report((3, 1, 2), (1, None))
check("explicit_ordinal_preserves_left_input_order",
tuple(row[0] for row in ordered.truth_rows) == (3, 1, 2) and
ordered.not_exists_selected == ordered.filtered_not_in_selected == (3, 2))
check("NOT_IN_is_three_valued_negation_of_IN",
all(row[2] == NEGATE[row[1]] for row in manual.truth_rows + empty_rhs.truth_rows))
control = sqlite3.connect(":memory:", autocommit=True)
try:
null_existence = control.execute(
"SELECT EXISTS(SELECT NULL),EXISTS(SELECT NULL WHERE NULL=1)").fetchone()
finally:
control.close()
check("EXISTS_counts_NULL_row_but_equality_correlation_filters_it",
null_existence == (1, 0) and all(row[3] in ("true", "false") and
row[4] in ("true", "false") for row in null_rhs.truth_rows))
no_nulls = missing_calibration_report((0, 1, 2, 3), (1, 2, 7))
check("null_free_right_side_agrees_in_nonnull_left_domain",
no_nulls.not_in_selected == no_nulls.not_exists_selected == (0, 3))
check("explicit_child_NULL_filter_matches_declared_absence_question",
manual.filtered_not_in_selected == manual.not_exists_selected == (2, 3)
and manual.not_in_selected == ())
left_forms = [p for n in range(4) for p in itertools.permutations((0, 1, 2), n)]
profiles = rows = 0
for size in range(5):
for children in itertools.product((None, 0, 1), repeat=size):
for sensors in left_forms:
actual = missing_calibration_report(sensors, children)
expected = truth_table_oracle(sensors, children)
if actual != expected:
raise AssertionError(("independent_value_fold", sensors, children, actual, expected))
profiles += 1
rows += len(actual.truth_rows)
check("finite_independent_three_value_family_ONE_group",
profiles == 1936 and rows == 3993)
invalid = invalid_input_controls()
check("whole_strict_input_validation_before_any_SQL", invalid["passed"])
resources = report_and_cleanup_controls()
check("immutable_fresh_reports_and_finally_connection_cleanup", resources["passed"])
assert len(checks) == 14 and all(type(x) is bool and x for x in checks.values())
return {"runtime": {"python": platform.python_version(),
"implementation": platform.python_implementation(),
"sqlite_library": sqlite3.sqlite_version},
"scope": "fixed scalar queries on private :memory: only; no disk DB, PostgreSQL, network, benchmark or real calibration",
"input_contract": {"sensor_ids": "exact distinct non-null ints0..7, tuple length0..8",
"child_ids": "None or exact ints0..7, tuple length0..8; duplicates allowed",
"units": "synthetic identifiers, no physical measurement"},
"truth_columns": ["sensor_id", "IN", "NOT_IN", "correlated_EXISTS", "correlated_NOT_EXISTS"],
"manual_report": asdict(manual), "empty_child_report": asdict(empty_rhs),
"NULL_only_child_report": asdict(null_rhs),
"unfiltered_NULL_row_exists_control": null_existence,
"independent_family": {"profiles": profiles, "predicate_rows": rows,
"left_forms": len(left_forms), "maximum_child_length": 4,
"counted_as_check_groups": 1},
"invalid_inputs": invalid, "resource_controls": resources,
"meaningful_named_groups": len(checks), "checks": checks,
"limits": ["Non-null scalar left IDs are a premise; no universal NOT_IN to NOT_EXISTS rewrite claim.",
"NULL child means an unassigned row. EXISTS itself counts NULL-containing rows; correlation equality controls witnesses.",
"No planner, speed, concurrency, data-authenticity or calibration-accuracy conclusion."]}
if __name__ == "__main__":
sys.stdout.reconfigure(encoding="utf-8", newline="\n")
result = run_example()
sys.stdout.buffer.write((json.dumps(result, ensure_ascii=True, indent=2) + "\n").encode("utf-8"))
چهارده گروهِ نامدار، شاهدِ دستی، تطبیقِ معلوم در حضورِ NULL، سمتِ راستِ خالی، ردیفِ فقط NULL، تکرار و جابهجاییِ فرزندها، ترتیبِ چپ، رابطهٔ IN و نقیضش، معنای EXISTS، حالتِ بدون NULL، فیلترِ صریحِ NULL، خانوادهٔ مستقل، ورودیِ نامعتبر و عمرِ گزارش و اتصال را در بر میگیرند. تمام حالتهای خانوادهٔ متناهی، یک گروهاند؛ تعدادِ پروفایل و ردیفِ مقایسهشده جداگانه در خروجی ثبت میشود.
{
"runtime": {
"python": "3.14.5",
"implementation": "CPython",
"sqlite_library": "3.50.4"
},
"scope": "fixed scalar queries on private :memory: only; no disk DB, PostgreSQL, network, benchmark or real calibration",
"input_contract": {
"sensor_ids": "exact distinct non-null ints0..7, tuple length0..8",
"child_ids": "None or exact ints0..7, tuple length0..8; duplicates allowed",
"units": "synthetic identifiers, no physical measurement"
},
"truth_columns": [
"sensor_id",
"IN",
"NOT_IN",
"correlated_EXISTS",
"correlated_NOT_EXISTS"
],
"manual_report": {
"truth_rows": [
[
1,
"true",
"false",
"true",
"false"
],
[
2,
"unknown",
"unknown",
"false",
"true"
],
[
3,
"unknown",
"unknown",
"false",
"true"
]
],
"not_in_selected": [],
"not_exists_selected": [
2,
3
],
"filtered_not_in_selected": [
2,
3
]
},
"empty_child_report": {
"truth_rows": [
[
1,
"false",
"true",
"false",
"true"
],
[
2,
"false",
"true",
"false",
"true"
]
],
"not_in_selected": [
1,
2
],
"not_exists_selected": [
1,
2
],
"filtered_not_in_selected": [
1,
2
]
},
"NULL_only_child_report": {
"truth_rows": [
[
1,
"unknown",
"unknown",
"false",
"true"
],
[
2,
"unknown",
"unknown",
"false",
"true"
]
],
"not_in_selected": [],
"not_exists_selected": [
1,
2
],
"filtered_not_in_selected": [
1,
2
]
},
"unfiltered_NULL_row_exists_control": [
1,
0
],
"independent_family": {
"profiles": 1936,
"predicate_rows": 3993,
"left_forms": 16,
"maximum_child_length": 4,
"counted_as_check_groups": 1
},
"invalid_inputs": {
"passed": true,
"invalid_type_profiles": 17,
"invalid_value_or_size_profiles": 8,
"connection_attempts": 0,
"generator_consumed": false
},
"resource_controls": {
"passed": true,
"actual_connections_closed": 4,
"expected_injected_error_identity_preserved": true
},
"meaningful_named_groups": 14,
"checks": {
"manual_unassigned_child_changes_anti_membership": true,
"concrete_match_wins_over_unknown_alternatives": true,
"empty_child_subquery_has_true_anti_membership": true,
"NULL_only_child_subquery_differs_from_empty": true,
"duplicate_children_and_NULLs_are_semantically_redundant": true,
"child_order_does_not_change_scalar_predicates": true,
"explicit_ordinal_preserves_left_input_order": true,
"NOT_IN_is_three_valued_negation_of_IN": true,
"EXISTS_counts_NULL_row_but_equality_correlation_filters_it": true,
"null_free_right_side_agrees_in_nonnull_left_domain": true,
"explicit_child_NULL_filter_matches_declared_absence_question": true,
"finite_independent_three_value_family_ONE_group": true,
"whole_strict_input_validation_before_any_SQL": true,
"immutable_fresh_reports_and_finally_connection_cleanup": true
},
"limits": [
"Non-null scalar left IDs are a premise; no universal NOT_IN to NOT_EXISTS rewrite claim.",
"NULL child means an unassigned row. EXISTS itself counts NULL-containing rows; correlation equality controls witnesses.",
"No planner, speed, concurrency, data-authenticity or calibration-accuracy conclusion."
]
}
برنامه فقط به کتابخانهٔ استاندارد وابسته است. نسخهٔ واقعیِ Python و هستهٔ متصلِ SQLite در خروجی ثبت میشود؛ مشاهدهٔ نسخهٔ تازهتر در سایتِ پروژه، نسخهٔ اجرا را عوض نمیکند. کنترلِ خطای ساختگیِ خواندن، برای بررسیِ finally و حفظِ هویتِ همان استثناست و شکستِ واقعیِ اجرای نویسنده نامیده نمیشود. برای مرزِ مقدار و ساختارِ دستور، درس اتصالِ مقدار به SQLite را جدا بخوانید؛ پارامترگذاری، معنای NOT IN را تغییر نمیدهد.
۵. چهار پرسش و مرزِ بازنویسیِ پرسوجو

پرسش اول: چرا افزودنِ یک رکوردِ بیصاحب، حسگرهای دو و سه را از NOT IN حذف میکند؟ پاسخ: چون نابرابریِ قطعی با همهٔ مقدارهای سمت راست اثبات نمیشود؛ مقایسه با NULL نامعلوم میماند و WHERE آن را نگه نمیدارد. این خروجی نمیگوید آن حسگرها فرزند دارند. در نسخهٔ مبتنی بر نبودِ شاهد، هر دو شناسه برمیگردند.
پرسش دوم: چرا حسگر یک نیز نامعلوم گزارش نمیشود؟ پاسخ: شاهدِ عددیِ برابری وجود دارد. IN با یک تطبیقِ درست، درست میشود و نقیضش نادرست است. ترتیبِ ردیفِ معلوم و NULL این معنا را عوض نمیکند؛ از این شاهد، ترتیبِ واقعیِ ارزیابیِ موتور را هم نتیجه نمیگیریم.
پرسش سوم: چه زمانی فیلترکردنِ NULLهای سمت راست برای این مثال کافی است؟ پاسخ: وقتی سمتِ چپ همان شناسههای غیرتهیِ قراردادی و پرسش، نبودِ تطبیق با شناسههای معلوم باشد. اگر NULL سمت چپ معنایی مجاز داشته باشد، باید تصمیم بگیریم آن ردیف چه سرنوشتی دارد. تابعِ فعلی چنین ورودیای را رد میکند و پاسخِ پنهانی برای آن نمیسازد.
پرسش چهارم: انتخابِ درستِ شناسهها، کالیبراسیون یا سرعتِ سامانه را تأیید میکند؟ پاسخ: خیر؛ فقط نبودِ شاهدِ برابری را در دو رابطهٔ ساختگی میسنجد. اعتبارِ فیزیکیِ کالیبراسیون، تازگیِ رکورد، تراکنشِ همزمان، طرحِ اجرا، کنترلِ دسترسی و کارایی در این آزمایش بررسی نشدهاند. منابعِ فنی در ۲۲ اکتبر ۲۰۲۶ خوانده شدند؛ تاریخِ دسترسی را تاریخِ انتشارِ اولیهٔ صفحه فرض نکردهایم.
منابع و مطالعهٔ بیشتر
- SQLite؛ تعریف کامل IN، NOT IN، EXISTS و زمینههای بولی
- PostgreSQL18؛ تعریف کامل EXISTS، IN و NOT IN در زیرپرسوجو
بررسی منابع: ۳۰ مهر ۱۴۰۵. تحلیلها و پیشنهادهای اجرایی، جمعبندی نویسندهاند.

