PostgreSQL ਪਾਬੰਦੀਆਂ (NOT NULL, CHECK, UNIQUE, FOREIGN KEY) 'ਤੇ ਭਰੋਸਾ ਕਰਕੇ AI-ਨਿਰਮਿਤ ਐਪਾਂ ਨੂੰ ਸੁਰੱਖਿਅਤ ਤੌਰ 'ਤੇ ਡਿਪਲੋਇ ਕਰੋ — ਕੋਡ ਅਤੇ ਟੈਸਟਾਂ ਤੋਂ ਪਹਿਲਾਂ ਡੇਟਾਬੇਸ ਨਿਯਮ ਲਗਾਓ।

AI-ਨਿਰਮਿਤ ਕੋਡ ਅਕਸਰ ਸਹੀ ਲੱਗਦਾ ਹੈ ਕਿਉਂਕਿ ਉਹ ਖੁਸ਼-ਰਾਹ (happy path) ਨੂੰ ਹੇਠਾਂ ਲੈਂਦਾ ਹੈ. ਅਸਲ ਐਪਾਂ ਵਿਚ ਸਮੱਸਿਆਵਾਂ ਮੈਦੀਅਨ ਵਿੱਚ ਆਉਂਦੀਆਂ ਹਨ: ਇੱਕ ਫਾਰਮ null ਦੀ ਥਾਂ ਖਾਲੀ ਸਟਰਿੰਗ ਭੇਜ ਦੇਂਦਾ ਹੈ, ਇੱਕ background job ਦੋ ਵਾਰੀ ਇੱਕੋ ਰਿਕਾਰਡ ਬਣਾਉਂਦਾ ਹੈ, ਜਾਂ ਇੱਕ delete ਮੂਲ ਰੋਅ ਨੂੰ ਹਟਾ ਕੇ ਬਚੇ ਹੋਏ ਬੱਚਿਆਂ ਨੂੰ ਛੱਡ ਦਿੰਦੀ ਹੈ. ਇਹ ਕੋਈ ਅਜੀਬ ਤਰ੍ਹਾਂ ਦੀਆਂ ਬੱਗਜ਼ ਨਹੀਂ ਹਨ. ਇਹ ਖਾਲੀ ਲਾਜਮੀ ਫੀਲਡ, duplicate "unique" ਮੁੱਲ ਅਤੇ orphan rows ਵਜੋਂ ਦਿਖਾਈ ਦਿੰਦੀਆਂ ਹਨ ਜੋ ਕਿਸੇ ਚੀਜ਼ ਵੱਲ ਨਹੀਂ ਇਸ਼ਾਰਾ ਕਰਦੇ.
ਇਹ ਗਲਤੀਆਂ code review ਅਤੇ ਬੁਨਿਆਦੀ ਟੈਸਟਾਂ ਵਿੱਚ ਵੀ ਚੁੱਕ ਜਾਦੀਆਂ ਹਨ: reviewer ਖ਼ਿਆਲ ਪੜ੍ਹਦੇ ਹਨ, ਹਰ ਏਜ ਕੇਸ ਨਹੀਂ. ਟੈਸਟ ਆਮ ਤੌਰ 'ਤੇ ਕੁਝ ਆਮ ਉਦਾਹਰਣਾਂ ਦੀ ਕਵਰੇਜ ਕਰਦੇ ਹਨ, ਨਾ ਕਿ ਹਫ਼ਤਿਆਂ ਦੇ ਯੂਜ਼ਰ ਵਿਵਹਾਰ, CSV imports, flaky network retries, ਜਾਂ concurrent requests. ਜੇ ਕੋਈ assistant ਕੋਡ ਬਣਾਇਆ ਹੈ, ਤਾਂ ਉਹ ਛੋਟੀ ਪਰ ਜਰੂਰੀ ਜਾਂਚਾਂ ਜਿਵੇਂ whitespace trim ਕਰਨਾ, ਰੇਂਜ ਵੇਰੀਫਾਈ ਕਰਨਾ, ਜਾਂ race conditions ਤੋਂ ਬਚਾਉਣ ਵਾਲੀਆਂ ਚੀਜ਼ਾਂ ਮੁੱਖ ਰਾਹੋਂ ਛੱਡ ਸਕਦਾ ਹੈ.
"ਪਹਿਲਾਂ_constraints, ਫਿਰ ਕੋਡ" ਦਾ ਮਤਲਬ ਇਹ ਹੈ ਕਿ ਤੁਸੀਂ ਬੇ-ਚਰਚਿਤ ਨਿਯਮਾਂ ਨੂੰ ਡੇਟਾਬੇਸ ਵਿੱਚ ਰੱਖਦੇ ਹੋ ਤਾਂ ਜੋ ਬੁਰਾ ਡੇਟਾ ਕਿਸੇ ਵੀ ਕੋਡ ਪਾਥ ਤੋਂ ਲਿਖਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੇ ਤਾਂ ਸੇਵ ਨਾ ਹੋਵੇ। ਤੁਹਾਡੀ ਐਪ ਫਿਰ ਵੀ ਇਨਪੁੱਟ ਦੀ ਵਰੁਜ਼ੀ (validation) ਕਰ ਸਕਦੀ ਹੈ ਤਾਂ ਜੋ error messages ਵਧੀਆ ਹੋਣ, ਪਰ ਡੇਟਾਬੇਸ ਸੱਚ ਨੂੰ enforce ਕਰਦਾ ਹੈ। ਇਥੇ PostgreSQL constraints ਚਮਕਦਾਰ ਹਨ: ਇਹ ਤੁਹਾਨੂੰ ਫ਼ੈਲਾਂ ਦੀਆਂ ਪੂਰੀਆਂ ਕੈਟੇਗਰੀਆਂ ਤੋਂ ਬਚਾਉਂਦੇ ਹਨ।
ਇੱਕ ਛੋਟਾ ਉਦਾਹਰਣ: ਇੱਕ ਛੋਟੀ CRM ਸੋਚੋ। ਇੱਕ AI-ਨਿਰਮਿਤ import script contacts ਬਣਾਉਂਦਾ ਹੈ। ਇੱਕ ਰੋਅ ਦਾ email "" (ਖਾਲੀ) ਹੈ, ਦੋ ਰੋਅਆਂ ਇੱਕੋ email ਵੱਖ-ਵੱਖ case ਵਿੱਚ ਦੁਹਰਾਉਂਦੀਆਂ ਹਨ, ਅਤੇ ਇੱਕ contact ਕਿਸੇ account_id ਨੂੰ refer ਕਰਦਾ ਹੈ ਜੋ ਹੋਰ ਪ੍ਰੋਸੈੱਸ ਵਿੱਚ delete ਹੋ ਚੁੱਕਾ ਹੈ। ਬਿਨਾਂ constraints ਦੇ, ਇਹ ਸਾਰਾ ਕੁਝ ਪ੍ਰੋਡਕਸ਼ਨ ਵਿੱਚ ਆ ਸਕਦਾ ਹੈ ਅਤੇ ਰਿਪੋਰਟਾਂ ਨੂੰ ਬਰਬਾਦ ਕਰ ਦੇਵੇਗਾ।
ਸਹੀ ਡੇਟਾਬੇਸ ਨਿਯਮਾਂ ਨਾਲ, ਉਹ ਲਿਖਤਾਂ ਤੁਰੰਤ fail ਹੋ ਜਾਂਦੀਆਂ ਹਨ, ਸਾਡੇ ਸਭ ਤੋਂ ਨੇੜੇ ਸਰੋਤ ਤੇ. ਲਾਜ਼ਮੀ ਫੀਲਡ ਮਿਸ ਨਹੀਂ ਹੋ ਸਕਦੀਆਂ, retries ਦੌਰਾਨ duplicates ਜ਼ੋਹਰ ਨਹੀਂ ਹੋ ਸਕਦੇ, ਰਿਸ਼ਤੇ deleted ਜਾਂ non-existent ਰਿਕਾਰਡ ਵੱਲ ਨਹੀਂ ਇਸ਼ਾਰਾ ਕਰ ਸਕਦੇ, ਅਤੇ ਮੁੱਲ allowed ਰੇਂਜ ਤੋਂ ਬਾਹਰ ਨਹੀਂ ਹੋ ਸਕਦੇ.
Constraints ਹਰ ਤਰ੍ਹਾਂ ਦੀ ਬੱਗ ਨੂੰ ਨਹੀਂ ਰੋਕਦੇ. ਇਹ confusing UI, ਗਲਤ discount calculation, ਜਾਂ slow query ਨੂੰ ਠੀਕ ਨਹੀਂ ਕਰਨਗੇ. ਪਰ ਇਹ ਮੰਦੀ-ਤਰ੍ਹਾਂ ਬੁਰਾ ਡੇਟਾ ਇਕੱਠਾ ਹੋਣ ਤੋਂ ਰੋਕਦੇ ਹਨ, ਜੋ ਅਕਸਰ ਉਹੀ ਥਾਂ ਹੈ ਜਿਥੇ "AI-ਨਿਰਮਿਤ edge-case ਬੱਗ" ਮਹਿੰਗੇ ਬਣ ਜਾਂਦੇ ਹਨ।
ਤੁਹਾਡੀ ਐਪ ਅਕਸਰ ਇੱਕ ਹੀ ਕੋਡਬੇਸ ਤੋਂ ਇੱਕ ਹੀ ਉਪਭੋਗਤਾ ਨਾਲ ਗੱਲ ਨਹੀਂ ਕਰਦੀ। ਇੱਕ ਆਮ ਪ੍ਰੋਡਕਟ ਵਿੱਚ web UI, mobile app, admin ਸਕਰੀਨ, background jobs, CSV imports, ਅਤੇ ਕਦੇ-ਕਦੇ third-party integrations ਹੁੰਦੇ ਹਨ। ਹਰ ਪਾਥ ਡੇਟਾ ਬਣਾ ਸਕਦਾ ਜਾਂ ਬਦਲ ਸਕਦਾ ਹੈ। ਜੇ ਹਰ ਪਾਥ ਨੂੰ ਇੱਕੋ ਨਿਯਮ ਯਾਦ ਰੱਖਣੇ ਪੈਣ, ਤਾਂ ਇੱਕ ਨਾ ਭੁੱਲ ਜਾਵੇਗਾ।
ਡੇਟਾਬੇਸ ਇਕੋ ਥਾਂ ਹੈ ਜਿਸ ਨੂੰ ਸਾਰੇ ਰਸਤੇ ਸਾਂਝਾ ਕਰਦੇ ਹਨ। ਜਦੋਂ ਤੁਸੀਂ ਇਸਨੂੰ ਅਖੀਰਲਾ gatekeeper ਮੰਨਦੇ ਹੋ, ਤਾਂ ਨਿਯਮ ਸਾਰਿਆਂ 'ਤੇ ਆਪਣੇ ਆਪ ਲਾਗੂ ਹੋ ਜਾਂਦੇ ਹਨ। PostgreSQL constraints "ਅਸੀਂ ਐਸਾ ਸਮਝਦੇ ਹਾਂ" ਨੂੰ "ਇਹ ਲਾਜ਼ਮੀ ਹੈ, ਨਹੀਂ ਤਾਂ write fail" ਵਿੱਚ ਬਦਲ ਦਿੰਦੇ ਹਨ।
AI-ਨਿਰਮਿਤ ਕੋਡ ਇਹ ਹੋਰ ਵੀ ਮਹੱਤਵਪੂਰਨ ਬਣਾ ਦਿੰਦਾ ਹੈ। ਇਕ ਮਾਡਲ React UI ਵਿੱਚ form validation ਜੋੜ ਸਕਦਾ ਹੈ ਪਰ background job ਵਿੱਚ ਇੱਕ corner case ਛੱਡ ਸਕਦਾ ਹੈ। ਜਾਂ ਇਹ ਖੁਸ਼-ਰਾਹ ਡੇਟਾ ਨੂੰ ਠੀਕ ਹੈਸੇਲ ਕਰੇਗਾ, ਪਰ ਜਦੋਂ ਅਸਲ ਕਸਟਮਰ ਕੁਝ ਅਣਉਮੀਦ ਕੀਤਾ ਭੇਜੇਗਾ ਤਾਂ ਟੁੱਟ ਜਾਵੇਗਾ। Constraints ਉਸ ਵੇਲੇ ਮੁੱਦੇ ਫੜ ਲੈਂਦੇ ਹਨ ਜਦੋਂ ਖਰਾਬ ਡੇਟਾ ਨੇ ਦੇਖਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ — ਨਾ ਕਿ ਹਫ਼ਤਿਆਂ ਬਾਅਦ ਜਦੋਂ ਤੁਸੀਂ ajeeb ਰਿਪੋਰਟਾਂ ਡੀਬੱਗ ਕਰ ਰਹੇ ਹੋ।
ਜਦੋਂ ਤੁਸੀਂ constraints skip ਕਰਦੇ ਹੋ, ਬੁਰਾ ਡੇਟਾ ਅਕਸਰ ਖਾਮੋਸ਼ ਹੋ ਕੇ ਅੰਦਰ ਆ ਜਾਂਦਾ ਹੈ। Save ਸਫਲ ਹੋ ਜਾਂਦਾ ਹੈ, ਐਪ ਅੱਗੇ ਵਧਦਾ ਹੈ, ਅਤੇ ਸਮੱਸਿਆ ਬਾਅਦ ਵਿੱਚ support ticket, billing mismatch, ਜਾਂ ਇਕ ਅਣਭਰੋਸੇਯੋਗ ਡੈਸ਼ਬੋਰਡ ਵਜੋਂ ਦਿਖਾਏਗੀ। صفائی ਮਹਿੰਗੀ ਹੁੰਦੀ ਹੈ ਕਿਉਂਕਿ ਤੁਸੀਂ ਇਤਿਹਾਸ ਨੂੰ ਠੀਕ ਕਰ ਰਹੇ ਹੋ, ਇੱਕ ਬੇਨਤੀ ਨੂੰ ਨਹੀਂ।
ਬੁਰਾ ਡੇਟਾ ਆਮ ਤੌਰ 'ਤੇ ਹਰ ਰੋਜ਼ ਦੀਆਂ ਸਥਿਤੀਆਂ ਰਾਹੀਂ ਛੁਪਦਾ ਹੈ: ਨਵਾਂ client app version ਇੱਕ field ਨੂੰ empty ਭੇਜਦਾ ਹੈ ਥੋੜ੍ਹੇ ਦੀ ਜਗ੍ਹਾ ਤੇ, ਇੱਕ retry duplicates ਬਣਾਉਂਦਾ ਹੈ, ਇੱਕ admin edit UI checks ਨੂੰ ਬਾਈਪਾਸ ਕਰ ਦਿੰਦਾ, ਇੱਕ import file inconsistent formatting ਵਾਲੀ ਹੁੰਦੀ ਹੈ, ਜਾਂ ਦੋ ਯੂਜ਼ਰ ਇੱਕੋ ਸਮੇਂ related records update ਕਰਦੇ ਹਨ।
ਇੱਕ ਉਪਯੋਕਤ ਮਾਨਸਿਕ ਮਾਡਲ: boundary 'ਤੇ ਹੀ data accept ਕਰੋ ਜੇ ਇਹ valid ਹੈ। ਅਮਲੀ ਤੌਰ 'ਤੇ, ਉਹ boundary ਡੇਟਾਬੇਸ ਨੂੰ ਵੀ ਸ਼ਾਮਿਲ ਕਰਨੀ ਚਾਹੀਦੀ ਹੈ, ਕਿਉਂਕਿ ਡੇਟਾਬੇਸ ਸਾਰੀਆਂ writes ਨੂੰ ਵੇਖਦਾ ਹੈ।
NOT NULL ਸਭ ਤੋਂ ਸਾਦਾ PostgreSQL constraint ਹੈ, ਅਤੇ ਇਹ ਕਾਫ਼ੀ ਵੱਡੀ ਕਲਾਸ ਦੀਆਂ ਬੱਗਜ਼ ਨੂੰ ਰੋਕਦਾ ਹੈ। ਜੇ ਕਿਸੇ ਰੋਅ ਲਈ ਇੱਕ ਮੁੱਲ ਮੌਜੂਦ ਹੋਣਾ ਲਾਜ਼ਮੀ ਹੈ ਤਾਂ ਡੇਟਾਬੇਸ ਨੂੰ enforce ਕਰੋ।
NOT NULL ਆਮ ਤੌਰ 'ਤੇ identifiers, ਲਾਜ਼ਮੀ ਨਾਮ, ਅਤੇ timestamps ਲਈ ਸਹੀ ਹੁੰਦਾ ਹੈ। ਜੇ ਤੁਸੀਂ ਉਸ ਮੁੱਲ ਬਿਨਾਂ ਇੱਕ ਵੈਧ ਰਿਕਾਰਡ ਨਹੀਂ ਬਣਾਉਣੇ, ਤਾਂ ਉਸਨੂੰ ਖਾਲੀ ਰੱਖਣ ਦੀ ਆਗਿਆ ਨਾ ਦਿਓ। ਇਕ ਛੋਟੀ CRM ਵਿੱਚ, ਇੱਕ lead ਜਿਸਦੇ ਕੋਲ owner ਜਾਂ created time ਨਹੀਂ, ਉਹ "partial lead" ਨਹੀਂ — ਉਹ ਤੂਟਿਆ ਹੋਇਆ ਡੇਟਾ ਹੈ ਜੋ ਬਾਅਦ ਵਿੱਚ ajeeb ਵਤੀਰਾ ਕਰੇਗਾ।
NULL ਆਮ ਤੌਰ 'ਤੇ AI-ਨਿਰਮਿਤ ਕੋਡ ਨਾਲ ਜ਼ਿਆਦਾ ਆਸਾਨੀ ਨਾਲ ਘੁਸ ਆ ਜਾਂਦਾ ਹੈ ਕਿਉਂਕਿ "optional" ਪਾਥ ਬਣਾਉਣਾ ਅਸਾਨ ਹੈ ਬਿਨਾਂ ਧਿਆਨ ਦਿਤੇ। ਇੱਕ form field UI ਵਿੱਚ optional ਹੋ ਸਕਦਾ ਹੈ, ਇੱਕ API missing key accept ਕਰ ਸਕਦਾ ਹੈ, ਅਤੇ create function ਦੀ ਇੱਕ branch value assign ਕਰਨ ਤੋਂ skip ਕਰ ਸਕਦੀ ਹੈ। ਸਭ ਕੁਝ compile ਹੁੰਦਾ ਹੈ ਅਤੇ ਖੁਸ਼-ਰਾਹ ਟੈਸਟ ਪਾਸ ਹੋਂਦਾ ਹੈ। ਫਿਰ ਅਸਲ ਯੂਜ਼ਰ CSV import ਕਰਦੇ ਹਨ ਖਾਲੀ ਸੈੱਲਾਂ ਨਾਲ, ਜਾਂ ਇੱਕ mobile client ਵੱਖ-ਵੱਖ payload ਭੇਜਦਾ ਹੈ, ਅਤੇ NULL ਡੇਟਾਬੇਸ ਵਿੱਚ ਆ ਜਾਂਦਾ ਹੈ।
ਇੱਕ ਚੰਗਾ pattern ਇਹ ਹੈ ਕਿ NOT NULL ਨੂੰ ਐਸੇ ਫੀਲਡਾਂ ਨਾਲ ਜੋੜੋ ਜੋ ਸਿਸਟਮ ਦੇ ਆਪਣੇ ਹਨ:
created_at TIMESTAMP NOT NULL DEFAULT now()status TEXT NOT NULL DEFAULT 'new'is_active BOOLEAN NOT NULL DEFAULT trueDefaults ਹਰ ਵਾਰੀ ਜਿੱਤ ਨਹੀਂ ਹੁੰਦੇ। NOT NULL ਨੂੰ ਪੂਰਾ ਕਰਨ ਲਈ user-provided ਫੀਲਡਾਂ ਜਿਵੇਂ email ਜਾਂ company_name ਨੂੰ default ਨਾ ਦਿਓ। ਇੱਕ ਖਾਲੀ ਸਟਰਿੰਗ NULL ਤੋਂ "ਜ਼ਿਆਦਾ ਵੈਧ" ਨਹੀਂ ਹੈ। ਇਹ ਸਿਰਫ ਸਮੱਸਿਆ ਨੂੰ ਛੁਪਾਉਂਦਾ ਹੈ।
ਜਦੋਂ ਤੁਹਾਨੂੰ ਸ਼ੱਕ ਹੋਵੇ, ਸੋਚੋ ਕਿ ਕੀ ਮੁੱਲ ਅਸਲੀ ਵਿੱਚ unknown ਹੈ, ਜਾਂ ਕੀ ਇਹ ਕਿਸੇ ਹੋਰ ਸਥਿਤੀ ਦੀ ਨੁਮਾਇੰਦਗੀ ਕਰਦਾ ਹੈ। ਜੇ "ਹਾਲੇ ਪ੍ਰਦਾਨ ਨਹੀਂ ਕੀਤਾ" ਮਨੁੱਖੀ ਮਾਨਤਾ ਰੱਖਦਾ ਹੈ, ਤਾਂ ਹਰ ਜਗ੍ਹਾ NULL ਦੀ ਆਗਿਆ ਦੇਣ ਦੀ ਥਾਂ ਇੱਕ ਵੱਖਰਾ state column ਸੋਚੋ। ਉਦਾਹਰਨ ਲਈ, phone ਨੂੰ nullable ਰੱਖੋ, ਪਰ phone_status ਰੱਖੋ ਜਿਸ ਵਿੱਚ missing, requested, ਜਾਂ verified ਵਰਗੀਆਂ ਵੈਲਯੂਜ਼ ਹੋਣ। ਇਹ ਤੁਹਾਡੇ ਕੋਡ ਵਿੱਚ ਮਤਲਬ ਨੂੰ consistent ਰੱਖਦਾ ਹੈ।
CHECK constraint ਤੁਹਾਡੇ table ਦਾ ਇੱਕ ਵਾਅਦਾ ਹੈ: ਹਰ ਰੋਅ ਨੂੰ ਇੱਕ ਨਿਯਮ ਪੂਰਾ ਕਰਨਾ ਹੈ, ਹਰ ਵਾਰ। ਇਹ ਇੱਕ ਆਸਾਨ ਤਰੀਕਾ ਹੈ edge cases ਨੂੰ ਰੋਕਣ ਦਾ, ਜਿਥੇ records ਕੋਡ ਵਿਚ ਠੀਕ ਦਿੱਸ ਸਕਦੇ ਹਨ ਪਰ ਅਸਲ ਵਿੱਚ ਮੈਨਿੰਗ ਨਹੀਂ ਰੱਖਦੇ।
CHECK constraints ਉਹਨਾਂ ਨਿਯਮਾਂ ਲਈ ਸਭ ਤੋਂ ਵਧੀਆ ਹਨ ਜੋ ਸਿਰਫ਼ ਇੱਕੋ ਰੋਅ ਦੀਆਂ ਵੈਲਯੂਜ਼ 'ਤੇ ਨਿਰਭਰ ਕਰਦੇ ਹਨ: ਨੰਬਰ ਰੇਂਜ, ਮਨਜ਼ੂਰ ਕੀਤੇ ਮੁੱਲ, ਅਤੇ ਕਾਲਮਾਂ ਦਰਮਿਆਨ ਸਾਦੇ ਸੰਬੰਧ।
-- 1) Totals should never be negative
ALTER TABLE invoices
ADD CONSTRAINT invoices_total_nonnegative
CHECK (total_cents >= 0);
-- 2) Enum-like allowed values without adding a custom type
ALTER TABLE tickets
ADD CONSTRAINT tickets_status_allowed
CHECK (status IN ('new', 'open', 'waiting', 'closed'));
-- 3) Date order rules
ALTER TABLE subscriptions
ADD CONSTRAINT subscriptions_date_order
CHECK (end_date IS NULL OR end_date >= start_date);
ਚੰਗਾ CHECK ਇਕ ਨਜ਼ਰ ਵਿੱਚ ਪੜ੍ਹਨ ਯੋਗ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ। ਇਸਨੂੰ ਤੁਹਾਡੇ ਡੇਟਾ ਲਈ ਦਸਤਾਵੇਜ਼ੀ (documentation) ਵਾਂਗ ਸਮਝੋ। ਛੋਟੇ expression, ਸਾਫ਼ constraint names, ਅਤੇ predictable patterns ਪਸੰਦ ਕਰੋ।
CHECK ਹਰ ਚੀਜ਼ ਲਈ ਠੀਕ ਹਥਿਆਰ ਨਹੀਂ ਹੈ। ਜੇ ਨਿਯਮ ਨੂੰ ਹੋਰ rows ਨੂੰ ਦੇਖਣਾ ਪੈਂਦਾ ਹੈ, aggregate ਡੇਟਾ ਦੀ ਲੋੜ ਹੈ, ਜਾਂ tables ਦਰਮਿਆਨ ਤੁਲਨਾ ਕਰਨੀ ਹੈ (ਉਦਾਹਰਨ ਲਈ, "ਕਿਸੇ account ਦਾ plan limit ਤੋਂ ਵੱਧ ਹੋਣਾ"), ਤਾਂ ਇਸਨੂੰ application code, triggers, ਜਾਂ controlled background job ਵਿੱਚ ਰੱਖੋ।
UNIQUE ਨਿਯਮ ਸਧਾਰਣ ਹੈ: ਡੇਟਾਬੇਸ ਉਸ column (ਜਾਂ columns ਦੇ ਕਮਬੋ) ਵਿੱਚ ਇੱਕੋ ਮੁੱਲ ਵਾਲੇ ਦੋ ਰੋਅਆਂ ਨੂੰ ਸਟੋਰ ਨਹੀਂ ਕਰਨ ਦਿੰਦਾ। ਇਹ ਉਹ ਸਾਰੀ ਕਿਸਮ ਦੀਆਂ ਬੱਗਜ਼ ਮਿਟਾ ਦਿੰਦਾ ਜਿਥੇ ਇੱਕ "create" path ਦੋ ਵਾਰੀ ਚੱਲ ਜਾਂਦਾ ਹੈ, ਇੱਕ retry ਹੁੰਦੀ ਹੈ, ਜਾਂ ਦੋ ਯੂਜ਼ਰ ਇੱਕੋ ਸਮੇਂ ਇੱਕੋ ਚੀਜ਼ ਸੋਮਿਤ ਕਰਦੇ ਹਨ।
UNIQUE ਇਹ ਗਰੰਟੀ ਦਿੰਦਾ ਹੈ ਕਿ ਜੋ ਮੁੱਲ ਤੁਸੀਂ define ਕਰਦੇ ਹੋ ਉਸ ਲਈ duplicate ਨਹੀਂ ਹੋਵੇਗਾ। ਇਹ ਇਹ ਗਰੰਟੀ ਨਹੀਂ ਦਿੰਦਾ ਕਿ ਮੁੱਲ ਮੌਜੂਦ ਹੈ (NOT NULL), ਕਿ ਇਹ ਕਿਸੇ ਫਾਰਮੈਟ ਦਾ ਪਾਲਣ ਕਰਦਾ ਹੈ (CHECK), ਜਾਂ ਕਿ ਇਹ ਤੁਹਾਡੇ ਸਮਝ ਅਨੁਸਾਰ equality ਹੈ (case, spaces, punctuation) ਜਦ ਤੱਕ ਤੁਸੀਂ ਇਹ define ਨਾ ਕਰੋ।
ਆਮ ਥਾਵਾਂ ਜਿੱਥੇ ਤੁਸੀਂ uniqueness ਚਾਹੁੰਦੇ ਹੋ: user table 'ਤੇ email, ਕਿਸੇ ਹੋਰ ਸਿਸਟਮ ਤੋਂ ਆਏ external_id, ਜਾਂ account ਅੰਦਰ unique name ਵਰਗਾ (account_id, name).
ਇੱਕ ਧਿਆਨ ਯੋਗ ਗੱਲ: NULL ਅਤੇ UNIQUE. PostgreSQL ਵਿੱਚ NULL "ਅਣਜਾਣ" ਮੰਨਿਆ ਜਾਂਦਾ ਹੈ, ਇਸ ਲਈ UNIQUE constraint ਹੇਠ multiple NULL values ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਜੇ ਤੁਹਾਡੀ ਮੁਰਾਦ ਹੈ "ਮੁੱਲ ਮੌਜੂਦ ਹੋਵੇ ਅਤੇ unique ਹੋਵੇ", ਤਾਂ UNIQUE ਨੂੰ NOT NULL ਨਾਲ ਜੋੜੋ।
ਯੂਜ਼ਰ-ਮੁਖੀ identifiers ਲਈ ਇੱਕ ਧਾਰਮਿਕ pattern case-insensitive uniqueness ਹੈ। ਲੋਕ "[email protected]" ਟਾਈਪ ਕਰਨਗੇ ਅਤੇ ਬਾਅਦ ਵਿੱਚ "[email protected]" ਅਗੇ ਚਾਹੁੰਦੇ ਹਨ ਕਿ ਉਹ ਇਕੋ ਹੀ ਹੋਵੇ।
-- Case-insensitive unique email
CREATE UNIQUE INDEX users_email_unique_ci
ON users (lower(email));
-- Unique contact name per account
ALTER TABLE contacts
ADD CONSTRAINT contacts_account_name_unique UNIQUE (account_id, name);
ਪਰਿਭਾਸ਼ਤ ਕਰੋ ਕਿ ਤੁਹਾਡੇ ਯੂਜ਼ਰਾਂ ਲਈ "duplicate" ਦਾ ਕੀ ਅਰਥ ਹੈ (case, whitespace, per-account vs global), ਫਿਰ ਇਸਨੂੰ ਇੱਕ ਵਾਰੀ encode ਕਰੋ ਤਾਂ ਕਿ ਹਰ ਕੋਡ ਪਾਥ ਇਹੋ ਨਿਯਮ ਮੰਨੇ।
FOREIGN KEY ਕਹਿੰਦੀ ਹੈ, "ਇਹ ਰੋਅ ਉੱਥੇ ਇਕ ਅਸਲ ਰੋਅ ਦੀ ਓੜ੍ਹਕੀ ਹੋਣੀ ਚਾਹੀਦੀ ਹੈ." ਬਿਨਾਂ ਇਸਦੇ, ਕੋਡ ਚਪਚਪਾ ਕੇ orphan records ਬਣਾਉ ਸਕਦਾ ਹੈ ਜੋ ਤਨਹਾ ਵੇਖਣ 'ਤੇ ਠੀਕ ਲੱਗਦੇ ਹਨ ਪਰ ਐਪ ਨੂੰ ਬਾਅਦ ਵਿੱਚ ਤੋੜ ਦੇਂਦੇ ਹਨ। ਉਦਾਹਰਨ ਲਈ: ਇੱਕ note ਜੋ ਇੱਕ customer ਨੂੰ refer ਕਰਦਾ ਹੈ ਜੋ delete ਹੋ ਚੁੱਕਾ ਹੈ, ਜਾਂ ਇਕ invoice ਜੋ ਇੱਕ ਅਜਿਹਾ user id ਵਲ ਇਸ਼ਾਰਾ ਕਰਦਾ ਹੈ ਜੋ ਕਦੇ ਮੌਜੂਦ ਹੀ ਨਹੀਂ ਸੀ।
Foreign keys ਸਭ ਤੋਂ ਜ਼ਰੂਰੀ ਹਨ ਜਦੋਂ ਦੋ ਕਾਰਵਾਈਆਂ ਨੇੜੇ-ਨੇੜੇ ਹੁੰਦੀਆਂ ਹਨ: ਇਕ delete ਅਤੇ ਇਕ create, timeout ਤੋਂ ਬਾਅਦ retry, ਜਾਂ ਇੱਕ background job stale data ਨਾਲ ਚੱਲ ਰਿਹਾ ਹੋਵੇ। ਡੇਟਾਬੇਸ ਹਰ ਰਾਹ ਨੂੰ ਨਿਯਮ enforce ਕਰਨ ਵਿੱਚ ਬਿਹਤਰ ਹੈ, ਬਜਾਏ ਕਿ ਹਰ ਐਪ ਰਸਤੇ ਨੂੰ ਯਾਦ ਰੱਖਣ ਦੇ।
ON DELETE ਓਪਸ਼ਨ ਨੂੰ ਰਿਸ਼ਤੇ ਦੇ ਅਸਲੀ-ਵਿਚਾਰ ਨਾਲ ਮੇਲ ਖਾਣਾ ਚਾਹੀਦਾ ਹੈ। ਪੁੱਛੋ: "ਜੇ parent ਗਾਇਬ ਹੋ ਜਾਵੇ, ਤਾਂ child ਨੂੰ ਜੀਊਣਾ ਚਾਹੀਦਾ ਹੈ?"
RESTRICT (ਜਾਂ NO ACTION): ਜੇ children ਮੌਜੂਦ ਹਨ ਤਾਂ parent delete ਨਹੀਂ ਹੋ ਸਕਦਾ।CASCADE: parent delete ਹੋਣ 'ਤੇ children ਵੀ delete ਹੋ ਜਾਂਦੇ ਹਨ।SET NULL: child ਨੂੰ ਰੱਖੋ ਪਰ link ਹਟਾ ਦਿਓ।CASCADE ਨਾਲ ਧਿਆਨ ਰੱਖੋ। ਇਹ ਸਹੀ ਹੋ ਸਕਦਾ ਹੈ, ਪਰ ਇੱਕ ਬੱਗ ਜਾਂ admin action ਦੇ ਨਾਲ ਇਹ ਤੁਹਾਡੇ ਉਮੀਦ ਤੋਂ ਜ਼ਿਆਦਾ ਡੇਟਾ ਮਿਟਾ ਸਕਦਾ ਹੈ।
Multi-tenant apps ਵਿੱਚ, foreign keys ਸਿਰਫ਼ correctness ਬਾਰੇ ਨਹੀਂ ਹਨ। ਇਹ cross-account leakage ਨੂੰ ਵੀ ਰੋਕਦੇ ਹਨ। ਇੱਕ ਆਮ pattern ਇਹ ਹੈ ਕਿ ਹਰ tenant-owned table ਵਿੱਚ account_id ਸ਼ਾਮਿਲ ਕਰੋ ਅਤੇ ਰਿਸ਼ਤਿਆਂ ਨੂੰ ਇਸ ਦੁਆਰਾ ਜੋੜੋ।
CREATE TABLE contacts (
account_id bigint NOT NULL,
id bigint GENERATED ALWAYS AS IDENTITY,
PRIMARY KEY (account_id, id)
);
CREATE TABLE notes (
account_id bigint NOT NULL,
id bigint GENERATED ALWAYS AS IDENTITY,
contact_id bigint NOT NULL,
body text NOT NULL,
PRIMARY KEY (account_id, id),
FOREIGN KEY (account_id, contact_id)
REFERENCES contacts (account_id, id)
ON DELETE RESTRICT
);
ਇਹ schema ਵਿੱਚ "who owns what" enforce ਕਰਦਾ ਹੈ: ਇੱਕ note ਇੱਕ ਵੱਖਰੇ account ਦੇ contact ਵੱਲ ਇਸ਼ਾਰਾ ਨਹੀਂ ਕਰ ਸਕਦੀ, ਭਾਵੇਂ app code (ਜਾਂ LLM-ਨਿਰਮਿਤ query) ਕੋਸ਼ਿਸ਼ ਕਰੇ।
ਸਭ ਤੋਂ ਪਹਿਲਾਂ ਇੱਕ ਛੋਟੀ ਲਿਸਟ ਲਿਖੋ invariants ਦੀ: ਉਹ ਸੱਚਾਈਆਂ ਜੋ ਹਮੇਸ਼ਾ ਸੱਚ ਹੋਣੀਆਂ ਚਾਹੀਦੀਆਂ ਹਨ। ਸਾਦੀ ਭਾਸ਼ਾ ਰੱਖੋ। "ਹਰ contact ਨੂੰ ਇੱਕ email ਚਾਹੀਦਾ ਹੈ." "ਇੱਕ status ਕੁਝ ਮਨਜ਼ੂਰ ਕੀਤੇ ਮੁੱਲਾਂ ਵਿੱਚੋਂ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ." "ਇੱਕ invoice ਨੂੰ ਇੱਕ ਅਸਲ customer ਦਾ ਹੋਣਾ ਲਾਜ਼ਮੀ ਹੈ." ਇਹ ਉਹ ਨਿਯਮ ਹਨ ਜੋ ਤੁਸੀਂ ਹਰ ਵਾਰੀ ਡੇਟਾਬੇਸ ਨੂੰ enforce ਕਰਵਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ।
ਮਾਈਗ੍ਰੇਸ਼ਨ ਨੂੰ ਛੋਟੇ-ਛੋਟੇ ਹਿੱਸਿਆਂ ਵਿੱਚ ਰੋਲ ਆਉਟ ਕਰੋ ਤਾਂ ਕਿ ਪ੍ਰੋਡਕਸ਼ਨ ਚੜ੍ਹ ਕੇ ਹੈਰਾਨ ਨਾ ਹੋਵੇ:
NOT NULL, UNIQUE, CHECK, FOREIGN KEY).ਗਦੀਲਾ ਹਿੱਸਾ ਮੌਜੂਦਾ ਬੁਰੇ ਡੇਟਾ ਨਾਲ ਹੈ। ਇਸਦਾ ਯੋਜਨਾ ਬਣਾਓ। Duplicates ਲਈ, ਇਕ winner row ਚੁਣੋ, ਬਾਕੀ merge ਕਰੋ, ਅਤੇ ਇੱਕ ਆਡੀਟ ਨੋਟ ਰੱਖੋ। Missing required fields ਲਈ, ਸਿਰਫ਼ ਜੇ ਇਹ ਸੁਰੱਖਿਅਤ ਹੋਵੇ ਤਾਂ safe default ਚੁਣੋ; ਨਹੀਂ ਤਾਂ quarantine ਕਰੋ। ਟੁੱਟੇ ਰਿਸ਼ਤਿਆਂ ਲਈ, child rows ਨੂੰ ਸਹੀ parent ਨੂੰ reassign ਕਰੋ ਜਾਂ ਬੁਰੇ rows ਨੂੰ ਹਟਾ ਦਿਓ।
ਹਰ migration ਤੋਂ ਬਾਅਦ, ਕੁਝ writes validate ਕਰੋ ਜੋ fail ਹੋਣੇ ਚਾਹੀਦੇ ਹਨ: ਇੱਕ ਰੋਅ insert ਕਰੋ ਜਿਸ ਵਿੱਚ ਲਾਜ਼ਮੀ ਮੁੱਲ ਮਿਸਿੰਗ ਹੋਵੇ, duplicate key insert ਕਰੋ, out-of-range value insert ਕਰੋ, ਅਤੇ missing parent row ਨੂੰ refer ਕਰੋ। Failed writes ਕੀਮਤੀ signal ਹੁੰਦੇ ਹਨ। ਇਹ ਦਿਖਾਉਂਦੇ ਹਨ ਕਿ ਐਪ ਕਿੱਥੇ "best effort" ਤੇ ਨਿਰਭਰ ਸੀ।
ਇੱਕ ਛੋਟੀ CRM ਦੀ ਤਸਵੀਰ ਕਰੋ: accounts (ਤੁਹਾਡੇ SaaS ਦੇ ਹਰ ਗਾਹਕ), ਉਹਨਾਂ ਦੀਆਂ ਕੰਪਨੀਆਂ, ਉਨ੍ਹਾਂ ਕੰਪਨੀਆਂ ਵਿੱਚ contacts, ਅਤੇ companies ਨਾਲ ਜੁੜੇ deals.
ਇਹ ਠੀਕ ਉਹ ਕਿਸਮ ਦਾ ਐਪ ਹੈ ਜੋ ਲੋਕ ਤੇਜ਼ੀ ਨਾਲ chat ਟੂਲ ਨਾਲ generate ਕਰਦੇ ਹਨ। demo ਵਿੱਚ ਇਹ ਠੀਕ ਦਿਖਦਾ ਹੈ, ਪਰ ਅਸਲ ਡੇਟਾ ਤੇਜ਼ੀ ਨਾਲ ਗੰਦਾ ਹੋ ਜਾਂਦਾ ਹੈ। ਦੋ ਬੱਗ ਅਕਸਰ ਜਲਦ ਦਿਖਾਈ ਦਿੰਦੇ ਹਨ: duplicate contacts (ਉਹੀ email ਥੋੜ੍ਹੀ ਵੱਖਰੀ ਵਿੱਧੀ ਨਾਲ ਦੂਜੀ ਵਾਰੀ ਦਾਖਲ), ਅਤੇ deals company ਬਿਨਾਂ ਬਣਾਉਣ ਦੇ ਕਿਉਂਕਿ ਇੱਕ ਕੋਡ ਪਾਥ company_id ਸੈੱਟ ਕਰਨਾ ਭੁੱਲ ਗਿਆ। ਇਕ ਹੋਰ ਆਮ ਗੱਲ negative deal value ਹੈ ਕਿਉਂਕਿ ਕਿਸੇ refactor ਜਾਂ parsing ਗਲਤੀ ਨੇ ਮੁੱਲ ਨੂੰ ਘਟਾ ਦਿੱਤਾ।
ਇਲਾਜ ਹੋਰ if-statements ਨਹੀਂ ਹੈ। ਇਹ ਕੁਝ ਸੋਚ-ਵਿਸ਼ੇਸ਼ constraints ਹਨ ਜੋ ਬੁਰਾ ਡੇਟਾ ਸਟੋਰ ਹੋਣਾ ਹੀ ਅਸੰਭਵ ਕਰ ਦਿੰਦੀਆਂ ਹਨ।
-- Contacts: prevent duplicates per account
ALTER TABLE contacts
ADD CONSTRAINT contacts_account_email_uniq UNIQUE (account_id, email);
-- Deals: require a company and keep the relationship valid
ALTER TABLE deals
ALTER COLUMN company_id SET NOT NULL,
ADD CONSTRAINT deals_company_fk
FOREIGN KEY (company_id) REFERENCES companies(id);
-- Deals: deal value cannot be negative
ALTER TABLE deals
ADD CONSTRAINT deals_value_nonneg CHECK (deal_value >= 0);
-- A few obvious required fields
ALTER TABLE companies
ALTER COLUMN name SET NOT NULL;
ALTER TABLE contacts
ALTER COLUMN email SET NOT NULL;
ਇਹ ਸਿਰਫ਼ ਸਖ਼ਤ ਹੋਣ ਲਈ ਨਹੀਂ ਹੈ। ਤੁਸੀਂ vague ਉਮੀਦਾਂ ਨੂੰ ਨਿਯਮਾਂ ਵਿੱਚ ਤਬਦੀਲ ਕਰ ਰਹੇ ਹੋ ਜੋ ਡੇਟਾਬੇਸ ਹਰ ਵਾਰੀ enforce ਕਰੇਗਾ, ਚਾਹੇ ਐਪ ਦਾ ਕਿਹੜਾ ਵੀ ਹਿੱਸਾ ਡੇਟਾ ਲਿਖੇ।
ਜਦੋਂ ਇਹ constraints ਲਾਗੂ ਹੋ ਜਾਂਦੇ ਹਨ, ਤਾਂ ਐਪ ਸਧਾਰਣ ਹੋ ਜਾਂਦੀ ਹੈ। ਤੁਸੀਂ ਕਈ defensive checks ਹਟਾ ਸਕਦੇ ਹੋ ਜੋ ਬਾਅਦ ਵਿੱਚ duplicates detect ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰਦੇ ਹਨ। failures clearer ਅਤੇ actionable ਹੋ ਜਾਂਦੇ ਹਨ (ਉਦਾਹਰਨ: "email already exists for this account" ਬਜਾਏ ajeeb downstream behavior ਦੇ). ਅਤੇ ਜਦੋਂ generated API route ਫੀਲਡ ਭੁੱਲ ਜਾਂਦਾ ਹੈ ਜਾਂ ਮੁੱਲ ਨੂੰ ਗਲਤ handle ਕਰਦਾ ਹੈ, write ਤੁਰੰਤ fail ਹੋ ਜਾਂਦਾ ਹੈ ਬਜਾਏ ਡੇਟਾਬੇਸ ਨੂੰ ਚੁਪਚਾਪ corrupt ਕਰਨ ਦੇ।
Constraints ਉਸ ਸਮੇਂ ਚੰਗੇ ਕੰਮ ਕਰਦੇ ਹਨ ਜਦੋਂ ਉਹ business ਦੇ ਤਰੀਕੇ ਨਾਲ ਮੇਲ ਖਾਂਦੇ ਹਨ। ਜ਼ਿਆਦਾਤਰ ਦੁੱਖ rules ਉਹਨਾਂ ਨੂੰ ਜੋੜਨ ਮਗਰੋਂ ਆਉਂਦੇ ਹਨ ਜੋ ਪਲ-ਵਾਰ "safe" ਲੱਗਦੇ ਹਨ ਪਰ ਬਾਅਦ ਵਿੱਚ ਅਚਾਨਕ ਹੋਰ ਅਵਸਰ ਰੋਕ ਦਿੰਦੇ ਹਨ।
ਇਕ ਆਮ ਫ਼ੁਟ-ਗਨ ON DELETE CASCADE ਨੂੰ ਹਰ ਜਗ੍ਹਾ ਵਰਤਣਾ ਹੈ। ਇਹ ਛង់ਦਾ ਦਿੱਸਦਾ ਹੈ ਜਦ ਤੱਕ ਕਿਸੇ ਨੇ parent delete ਕਰ ਦਿਤਾ ਅਤੇ ਡੇਟਾਬੇਸ ਸਾਫ਼-ਸਫਾਈ ਦੀ ਤਰ੍ਹਾਂ ਸਿਸਟਮ ਦਾ ਅੱਧਾ ਹਿੱਸਾ ਮਿਟਾ ਦੇਵੇ। Cascades draft line items ਵਰਗੇ sach-owned ਡੇਟਾ ਲਈ ਠੀਕ ਹੋ ਸਕਦੇ ਹਨ, ਪਰ customers, invoices, tickets ਵਰਗੀਆਂ records ਲਈ ਖਤਰਨਾਕ ਹੋ ਸਕਦੇ ਹਨ। ਜੇ ਤੁਸੀਂ ਯਕੀਨ ਨਹੀਂ, RESTRICT ਪਸੰਦ ਕਰੋ ਅਤੇ deletes intentional handle ਕਰੋ।
ਇੱਕ ਹੋਰ ਸਮੱਸਿਆ ਇਹ ਹੈ ਕਿ CHECK rules ਬਹੁਤ ਨਿੱਕੇ ਲਿਖੇ ਜਾਂਦੇ ਹਨ। "Status must be 'new', 'won', or 'lost'" ਠੀਕ ਲੱਗਦਾ ਹੈ ਜਦ ਤਕ ਤੁਹਾਨੂੰ "paused" ਜਾਂ "archived" ਦੀ ਲੋੜ ਨਾ ਪਏ। ਚੰਗਾ CHECK constraint ਇੱਕ ਸਥਿਰ ਸੱਚਾਈ ਵੇਖਾਉਂਦਾ ਹੈ, ਨਾ ਕਿ ਇੱਕ ਅਸਥਾਈ UI ਚੋਇਸ। "amount >= 0" ਵਧੀਆ ਜੀਉਂਦਾ ਹੈ। "country in (...)" ਅਕਸਰ ਨਹੀਂ।
ਜਦੋਂ ਟੀਮਾਂ generated code ਦੇ ਚੱਲਣ ਤੋਂ ਬਾਅਦ constraints ਜੋੜਦੀਆਂ ਹਨ, ਕੁਝ ਗਲਤੀਆਂ ਵਾਰ-ਵਾਰ ਦਿਖਾਈ ਦਿੰਦੀਆਂ ਹਨ:
ਪਰਫਾਰਮੈਂਸ ਬਾਰੇ: PostgreSQL UNIQUE ਲਈ ਆਪਣੇ ਆਪ index ਬਣਾਉਂਦਾ ਹੈ, ਪਰ foreign keys referencing column ਲਈ ਆਟੋ-ਇੰਡੈਕਸ ਨਹੀਂ ਬਣਾਉਂਦਾ। ਉਸ ਇੰਡੈਕਸ ਦੇ ਬਗੈਰ, parent ਉੱਤੇ updates ਅਤੇ deletes slow ਹੋ ਸਕਦੇ ਹਨ ਕਿਉਂਕਿ Postgres child table ਨੂੰ scan ਕਰਕੇ references check ਕਰਦਾ ਹੈ।
ਕਿਸੇ ਨਿਯਮ ਨੂੰ tighten ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ, ਉਹ ਮੌਜੂਦਾ rows ਲੱਭੋ ਜੋ fail ਕਰਨਗੇ, ਫੈਸਲਾ ਕਰੋ ਕਿ ਉਹਨਾਂ ਨੂੰ fix ਕਰਨਾ ਹੈ ਜਾਂ quarantine ਕਰਨਾ ਹੈ, ਅਤੇ ਤਬ changes step-by-step ਰੋਲ ਕਰੋ।
ship ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ, ਹਰ table ਲਈ ਪੰਜ ਮਿੰਟ ਲਵੋ ਅਤੇ ਲਿਖੋ ਕਿ ਕੀ-ਕਿ ਹਮੇਸ਼ਾ ਸੱਚ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ। ਜੇ ਤੁਸੀਂ ਇਸਨੂੰ ਸਾਦੀ ਅੰਗਰੇਜ਼ੀ ਵਿੱਚ ਕਹਿ ਸਕਦੇ ਹੋ, ਤਾਂ ਆਮ ਤੌਰ 'ਤੇ ਤੁਸੀਂ ਇਸਨੂੰ constraint ਨਾਲ enforce ਕਰ ਸਕਦੇ ਹੋ।
ਹਰ table ਲਈ ਇਹ ਸਵਾਲ ਪੁڇੋ:
ਜੇ ਤੁਸੀਂ ਕਿਸੇ chat-driven build tool ਵਰਤ ਰਹੇ ਹੋ, ਤਾਂ ਉਹ invariants ਨੂੰ data acceptance criteria ਵਾਂਗ treat ਕਰੋ, ਨਾ ਕਿ optional notes ਵਾਂਗ। ਉਦਾਹਰਨ: "A deal amount must be non-negative," "A contact email is unique per workspace," "A task must reference a real contact." ਜਿੰਨਾ explicit ਨਿਯਮ ਹੋਣਗੇ, ਉਨਾ ਘੱਟ room ਰਹੇਗਾ accidental edge cases ਲਈ।
Koder.ai (koder.ai) ਵਿੱਚ planning mode, snapshots and rollback, ਅਤੇ source code export ਵਰਗੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਹਨ, ਜੋ schema changes ਨੂੰ ਸੁਰੱਖਿਅਤ ਢੰਗ ਨਾਲ iterate ਕਰਨ ਵਿੱਚ ਆਸਾਨੀ ਕਰ ਸਕਦੀਆਂ ਹਨ ਜਦ ਤੁਸੀਂ constraints ਕਦਮ-ਦਰ-ਕਦਮ ਕੜੇ ਕਰ ਰਹੇ ਹੋ।
ਇੱਕ ਸਧਾਰਣ rollout pattern ਜੋ ਅਸਲ ਟੀਮਾਂ ਵਿੱਚ ਕੰਮ ਕਰਦਾ ਹੈ: ਇੱਕ high-value table ਚੁਣੋ (users, orders, invoices, contacts), 1-2 constraints ਜੋ ਸਭ ਤੋਂ ਵੱਡੀਆਂ failure ਨੂੰ ਰੋਕਦੀਆਂ ਹਨ (ਅਕਸਰ NOT NULL ਅਤੇ UNIQUE) ਜੋੜੋ, ਜੋ writes fail ਹੁੰਦੇ ਹਨ ਉਹਨਾਂ ਨੂੰ fix ਕਰੋ, ਫਿਰ ਦੁਹਰਾਓ। ਸਮੇਂ ਦੇ ਨਾਲ rules tighten ਕਰਨਾ ਇੱਕ ਵੱਡੀ ਜੋਖ਼ਿਮ-ਭਰੀ migration ਤੋਂ ਵਧੀਆ ਹੈ।