پارامتر SQL برای مقدار است؛ علامتِ? نامِ ستون یا قطعهٔ دلخواهِ دستور را جایگزین نمیکند. در اتصالِ یک ابزارِ داده، باید مقدارِ ورودی را bind و ساختارِ query را از قالبِ مجاز انتخاب کرد. تمرین این صفحه سه رکوردِ ساختگی در پایگاهِ حافظهای میسازد و رفتارِ مقدارِ کوتیشندار، ورودیِ شبیه به دستور و انتخابِ ستون را واقعاً مقایسه میکند. هیچ پایگاهِ بیرونی آزمایش نمیشود.
مقدارِ عادیِ کوتیشندار را درست بخوانیم
سه ردیفِ اصیل با idهای۱تا۳ و nameهای alpha، O'Reilly و gamma داریم. برای یافتنِ ردیفِ دوم، query ثابتِ WHERE name=? و tupleِیکعضویِ حاویِ مقدار را به execute میدهیم. نتیجه دقیقاً همان ردیفِ۲ است؛ وجودِ apostrophe در داده، ساختارِ SQL را نمیشکند.
parameter را با quoteکردنِ دستی یا چسباندنِ رشتهٔ ورودی به متنِ query یکی نگیریم. کتابخانهٔ موجود مقدار را در جایگاهِ داده میگیرد. این کار، درستبودنِ معنای name یا اجازهٔ caller برای دیدنِ ردیف را تعیین نمیکند؛ query و قواعدِ اختیار همچنان باید از طرفِ برنامه روشن باشند.
یک ضدنمونهٔ بیاثر، فقط داخلِ حافظه
برای مشاهدهٔ فرقِ داده و دستور، رشتهٔ ثابتِ آموزشیِ ' OR 1=1 -- را در همان جدولِ ساختگی به دو مسیر میدهیم. مسیرِ نادرست آن را به SELECT میچسباند و هر سه ردیف را برمیگرداند. مسیرِ bindشده دقیقاً همان رشته را یک مقدارِ name میداند و چون چنین نامی در fixture نیست، نتیجهٔ خالی میدهد.
این مثال فقط SELECT روی :memory: تازه است؛ هیچ حذف، تغییرِ جدول، درخواست به سایت یا آزمونِ SQL injection روی CRM انجام نمیدهد. بعد از مقایسه، کلِ جدول با سه ردیفِ اولیه برابر کنترل میشود. نتیجهٔ این ضدنمونه را گزارشِ امنیتِ کلِ برنامه یا کشفِ آسیبپذیری در سامانهٔ واقعی نمینامیم.
SELECT ? ستون انتخاب نمیکند
در آزمایشِ بعد، SELECT ? FROM item ORDER BY id را با مقدارِ' name ' بدونِ فاصلههای نمایشی اجرا میکنیم. خروجی برای هر یک از سه ردیف، رشتهٔ literalِname است؛ محتویاتِ ستونِname انتخاب نشدهاند. نامِ ستون، بخشی از ساختارِ دستور است و placeholderِمقدار جای آن را نمیگیرد.
| نیاز | مسیرِ تمرین | کنترلِ لازم |
|---|---|---|
| جستوجوی مقدار | WHERE name=? | tupleِمقدار با تعدادِ درست |
| مقدارِ نامدار | WHERE name=:value | dict با کلیدِ لازم |
| انتخابِ ترتیبِ نمایش | نگاشتِ ثابتِ سمتِ برنامه | ردِ selector ناشناخته |
ساختار را از فهرستِ ثابت انتخاب کنیم
برای ORDER BY، نگاشتی با دو گزینهٔ نامدار تعریف کردهایم: name-up و id-down. هر کدام به یک عبارتِ ثابتِ نوشتهشده توسطِ برنامه وصل میشود. ورودیِ caller خودِ عبارتِSQL نیست؛ فقط کلیدِ انتخاب است. نمونهٔ id-down واقعاً ردیفها را با ترتیب۳،۲،۱ برمیگرداند و انتخابِ ناشناخته پیش از ساختِ query رد میشود.
این روش، مجوزِ چسباندنِ identifier دلخواهِ مدل یا escapeکردنِ حدسیِ آن نیست. اگر به ستونهای بیشتری نیاز دارید، فهرست و اختیارِ هر انتخاب باید آگاهانه تعریف شوند. bindکردنِ یک مقدار نیز tenant filter، مالکیتِ رکورد یا محدودیتِ نقش را خودکار به query اضافه نمیکند.
qmark و named را با ظرفِ درست بدهیم
در سبکِqmark، تعدادِ مقدارهای sequence باید با تعدادِ placeholderها برابر باشد. در نمونه، tupleِخالی برای یک? واقعاً ProgrammingError میدهد. در سبکِnamed، dict باید کلیدِvalue را داشته باشد؛ dictِخالی هم خطای واقعی میدهد. این حالتها در JSONِنتیجه کنارِ انتظار ثبت شدهاند.
یک نکتهٔ مهمِ API این است که کلیدِ اضافیِ dictِnamed در این نسخه نادیده گرفته میشود. کد با {'value':'alpha','extra':'unused'} واقعاً ردیفِ۱ را میگیرد. اگر wrapperِشما فیلدِ اضافی را رد میکند، آن سیاستِ سختگیرانهٔ wrapper است؛ نباید آن را بیدلیل رفتارِ همیشگیِ خودِ sqlite3 معرفی کرد.
آزمونِ کوچک چه چیزی را ثابت کرد؟
نسخهٔ اجرا SQLite۳٫۵۳٫۱ و Python۳٫۱۲٫۱۴ است. مقدارِ عادیِ کوتیشندار، ضدنمونهٔ SELECT، literalبودنِ? در فهرستِ انتخاب، ترتیبِ ثابت، named با کلیدِ اضافه و سه مسیرِ خطا اجرا شدهاند. تمامِ ردیفهای fixture در پایان ثابتاند. هیچ دستورِ دلخواهِ مدل، دادهٔ مشتری یا اتصالِ عملیاتی اجرا نشده است.
اعتبارسنجیِ فراخوانیِ ابزار نامِ تابع، آرگومان و اختیار را جدا کنترل میکند؛ این صفحه مرزِ داخلِ query را نشان میدهد. اجرای قیدِ رابطه نیز مسئلهٔ مستقلی است و bind بهتنهایی آن را فعال نمیکند.
برای بررسیِ اتصال در راهکارهای اپرا، queryهایِمجاز، selectorها و نقشِ caller را همراهِ نمونه مشخص کنید. این راهنما SQLِآزاد یا دسترسیِپایگاه در محصول را وعده نمیدهد؛ خروجیاش یک مقایسهٔ قابلِتکرار میانِ مقدارِ ورودی و ساختارِ دستور است.
فایل تمرین و منبع
کد کامل تمرینِ محلی و کنترلهای آن · نمونههای اصیل و نتیجهٔ اجرای واقعیِ همین کد
منابع در 2026-11-04 خوانده شدند؛ این تاریخ، تاریخ انتشار منبع نیست. مثالها و فایلهای این راهنما آموزشی و ساختهٔ تحریریهاند.