AI एजेंट · पाठ

SQL क्वेरी बनाना और सत्यापित करना

सुरक्षित SQL के लिए प्रॉम्प्ट पैटर्न: केवल-SELECT मोड और पैरामीटरयुक्त क्वेरी।

पाठ 3, कुल 4 में से13 चरण

SQL क्वेरी बनाना और सत्यापित करना, CoddyKit पर AI एजेंट का एक निःशुल्क पाठ है। यह 4 में से 3वाँ पाठ है। आप नीचे पूरा पाठ निःशुल्क पढ़ सकते हैं—फिर अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर के साथ ब्राउज़र में इसका व्यावहारिक अभ्यास कर सकते हैं। यह AI एजेंट सीखने के मार्ग का हिस्सा है और आपकी प्रगति वेब तथा CoddyKit ऐप पर सिंक होती रहती है। AI एजेंट पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

एसक्यूएल बनाने का लक्ष्य

एसक्यूएल क्वेरी बनाना काम का केवल आधा हिस्सा है। वास्तविक डेटाबेस पर उसे चलाने से पहले आपको सत्यापित करना होगा कि क्वेरी सुरक्षित है, वाक्य-विन्यास की दृष्टि से सही है और उपयोगकर्ता के आशय के अनुरूप ही काम करती है।

इस पाठ में केवल SELECT लागू करना, पार्स करना, सुरक्षित निष्पादन और EXPLAIN योजना का सत्यापन शामिल है।

केवल SELECT मोड लागू करना

NL से एसक्यूएल एजेंट द्वारा किया जा सकने वाला सबसे खतरनाक काम किसी विनाशकारी स्टेटमेंट को चलाना है। LLM चाहे जो भी लौटाए, हमेशा केवल SELECT मोड लागू करें।

साधारण स्ट्रिंग जाँच पर्याप्त नहीं है — उचित एसक्यूएल पार्सर का उपयोग करें।

import sqlparse

def is_select_only(sql):
    parsed = sqlparse.parse(sql)
    if not parsed:
        return False
    for statement in parsed:
        stmt_type = statement.get_type()
        if stmt_type != 'SELECT':
            print(f'Blocked statement type: {stmt_type}')
            return False
    return True

# Test
print(is_select_only('SELECT * FROM users'))  # True
print(is_select_only('DROP TABLE users'))      # False — Blocked

रक्षा की अतिरिक्त परत के रूप में कीवर्ड ब्लॉकलिस्ट

sqlparse का उपयोग करने पर भी द्वितीयक सुरक्षा के रूप में कीवर्ड ब्लॉकलिस्ट जोड़ें। कुछ एसक्यूएल इंजेक्शन पार्सर को चकमा दे सकते हैं। निष्पादन से पहले खतरनाक कीवर्ड की जाँच करने से सुरक्षा की एक अतिरिक्त परत मिलती है।

DANGEROUS_KEYWORDS = [
    'INSERT', 'UPDATE', 'DELETE', 'DROP', 'CREATE',
    'ALTER', 'TRUNCATE', 'GRANT', 'REVOKE', 'EXEC',
    'EXECUTE', 'CALL', 'MERGE'
]

def passes_blocklist(sql):
    sql_upper = sql.upper()
    for keyword in DANGEROUS_KEYWORDS:
        # Check as whole word to avoid false positives like 'CREATED_AT'
        import re
        if re.search(r'\b' + keyword + r'\b', sql_upper):
            raise ValueError(f'Blocked keyword detected: {keyword}')
    return True

def validate_sql(sql):
    if not is_select_only(sql):
        raise ValueError('Only SELECT statements are allowed')
    passes_blocklist(sql)
    return True

sqlparse से एसक्यूएल पार्स करना

sqlparse एसक्यूएल स्ट्रिंग को चलाए बिना उसका टोकनीकरण और पार्सिंग करता है। आप क्वेरी की संरचना की जाँच कर सकते हैं, तालिका नाम निकाल सकते हैं और वाक्य-विन्यास संबंधी समस्याओं का पता लगा सकते हैं।

pip install sqlparse से इंस्टॉल करें।

import sqlparse
from sqlparse.sql import IdentifierList, Identifier
from sqlparse.tokens import Keyword, DML

def extract_table_names(sql):
    parsed = sqlparse.parse(sql)[0]
    tables = []
    from_seen = False
    for token in parsed.tokens:
        if token.ttype is DML and token.value.upper() == 'SELECT':
            continue
        if token.ttype is Keyword and token.value.upper() in ('FROM', 'JOIN'):
            from_seen = True
            continue
        if from_seen:
            if isinstance(token, Identifier):
                tables.append(token.get_name())
            elif isinstance(token, IdentifierList):
                for item in token.get_identifiers():
                    tables.append(item.get_name())
            from_seen = False
    return tables

print(extract_table_names('SELECT u.name FROM users u JOIN orders o ON u.id = o.user_id'))
# ['users', 'orders']

स्कीमा में तालिकाओं का अस्तित्व सत्यापित करना

तैयार की गई एसक्यूएल से तालिका नाम निकालने के बाद, उनका अपनी ज्ञात स्कीमा से मिलान करें। यदि LLM ने किसी तालिका नाम की कल्पना कर ली है, तो अस्पष्ट डेटाबेस त्रुटि मिलने की प्रतीक्षा करने के बजाय निष्पादन से पहले क्वेरी अस्वीकार कर दें।

def validate_tables_exist(sql, known_tables):
    used_tables = extract_table_names(sql)
    invalid = [t for t in used_tables if t and t not in known_tables]
    if invalid:
        raise ValueError(
            f'Query references non-existent tables: {invalid}. '
            f'Available tables: {list(known_tables)[:10]}...'
        )
    return True

# Usage
known = set(build_schema_dict(conn).keys())
try:
    validate_tables_exist(generated_sql, known)
except ValueError as e:
    # Send error back to LLM for correction
    corrected_sql = llm_fix_sql(generated_sql, str(e))
    print('Corrected SQL:', corrected_sql)

पैरामीटरयुक्त निष्पादन

उपयोगकर्ता द्वारा दिए गए मानों को एसक्यूएल में डालने के लिए कभी भी स्ट्रिंग फ़ॉर्मैटिंग का उपयोग न करें। LLM क्वेरी तैयार करता हो, तब भी एसक्यूएल इंजेक्शन रोकने के लिए उपयोगकर्ता द्वारा दिए गए फ़िल्टर मान पैरामीटर के रूप में भेजे जाने चाहिए।

import sqlite3

conn = sqlite3.connect(':memory:')
conn.execute('CREATE TABLE orders (status TEXT, user_id INTEGER)')
conn.execute("INSERT INTO orders VALUES ('pending', 42)")

def safe_execute(conn, sql_template, params=()):
    """Execute with parameterized values."""
    cur = conn.cursor()
    cur.execute(sql_template, params)  # driver handles escaping
    columns = [d[0] for d in cur.description]
    rows = cur.fetchmany(200)
    return {'columns': columns, 'rows': rows}

sql = 'SELECT * FROM orders WHERE status = ? AND user_id = ?'
result = safe_execute(conn, sql, params=('pending', 42))
print(result)

निष्पादन से पहले EXPLAIN योजना

बड़ी तालिकाओं पर महँगी क्वेरी के लिए वास्तविक क्वेरी चलाने से पहले EXPLAIN चलाएँ। यदि योजनाकार दस लाख पंक्तियों वाली तालिका पर पूर्ण तालिका स्कैन दिखाता है, तो उपयोगकर्ता को चेतावनी दें या क्वेरी अस्वीकार कर दें।

def check_explain_plan(conn, sql):
    explain_sql = f'EXPLAIN {sql}'
    with conn.cursor() as cur:
        cur.execute(explain_sql)
        plan = '\n'.join(row[0] for row in cur.fetchall())

    # Check for sequential scans on large tables
    if 'Seq Scan' in plan:
        print('WARNING: Query involves a sequential scan')
        print(plan)
        return {'safe': False, 'plan': plan, 'warning': 'Sequential scan detected'}

    return {'safe': True, 'plan': plan}

# Use before executing
plan_result = check_explain_plan(conn, generated_sql)
if not plan_result['safe']:
    print(f'Optimization hint: {plan_result["warning"]}')

पंक्ति सीमा लागू करना

LLM बिना LIMIT के SELECT * FROM logs तैयार कर सकता है, जिससे संभावित रूप से लाखों पंक्तियाँ लौट सकती हैं। हमेशा पंक्तियों की अधिकतम संख्या लागू करें — या तो क्वेरी में LIMIT जोड़कर या सीमित परिणाम-समूह प्राप्त करके।

import re

MAX_ROWS = 500

def enforce_row_limit(sql, max_rows=MAX_ROWS):
    sql_upper = sql.upper().rstrip().rstrip(';')

    # Check if LIMIT already present
    if re.search(r'\bLIMIT\b', sql_upper):
        # Extract current limit and enforce maximum
        match = re.search(r'LIMIT\s+(\d+)', sql_upper)
        if match:
            current = int(match.group(1))
            if current > max_rows:
                sql = re.sub(r'LIMIT\s+\d+', f'LIMIT {max_rows}', sql, flags=re.IGNORECASE)
    else:
        sql = sql.rstrip(';') + f' LIMIT {max_rows}'

    return sql

print(enforce_row_limit('SELECT * FROM users'))
# SELECT * FROM users LIMIT 500

LLM आउटपुट से स्वच्छ एसक्यूएल निकालना

LLM अक्सर एसक्यूएल को मार्कडाउन कोड ब्लॉक (```sql ... ```) में लपेटकर या व्याख्यात्मक पाठ के साथ लौटाते हैं। पार्स करने या चलाने से पहले आपको कच्ची एसक्यूएल निकालनी होगी।

import re

CODE_FENCE = chr(96) * 3  # three backticks, built at runtime to avoid template issues

def extract_sql(llm_response):
    # Remove markdown code blocks ('''sql ... ''' or ''' ... ''')
    pattern = CODE_FENCE + r'(?:sql)?\s*([\s\S]+?)' + CODE_FENCE
    match = re.search(pattern, llm_response, re.IGNORECASE)
    if match:
        return match.group(1).strip()

    # If no code block, look for SELECT statement
    match = re.search(r'(SELECT\s+[\s\S]+?;)', llm_response, re.IGNORECASE)
    if match:
        return match.group(1).strip()

    # Fallback: strip common preamble phrases
    cleaned = re.sub(r'^(Here is|The SQL query is|Query:)[^\n]*\n', '',
                     llm_response, flags=re.IGNORECASE).strip()
    return cleaned

if __name__ == '__main__':
    demo_response = 'Here is the SQL query:\n' + CODE_FENCE + 'sql\nSELECT * FROM users;\n' + CODE_FENCE
    print(extract_sql(demo_response))

पूर्ण सत्यापन प्रक्रिया

सभी सत्यापन चरणों को एक ही फ़ंक्शन में जोड़ें, जो कच्चे LLM आउटपुट को ले और सुरक्षित, चलाने योग्य एसक्यूएल स्ट्रिंग लौटाए या पुनर्प्राप्ति के लिए वर्णनात्मक संदेश वाली त्रुटि उत्पन्न करे।

def validate_and_prepare_sql(llm_output, known_tables, max_rows=500):
    # Step 1: extract raw SQL
    sql = extract_sql(llm_output)
    if not sql:
        raise ValueError('No SQL found in LLM response')

    # Step 2: type check
    if not is_select_only(sql):
        raise ValueError('Only SELECT queries allowed')

    # Step 3: keyword blocklist
    passes_blocklist(sql)

    # Step 4: table existence check
    validate_tables_exist(sql, known_tables)

    # Step 5: row limit
    sql = enforce_row_limit(sql, max_rows)

    return sql

# Full flow
try:
    safe_sql = validate_and_prepare_sql(llm_output, known_tables)
    result = safe_execute(conn, safe_sql)
except ValueError as e:
    corrected = llm_fix_sql(llm_output, str(e))
    safe_sql = validate_and_prepare_sql(corrected, known_tables)
    result = safe_execute(conn, safe_sql)

केवल-पठन वाला डेटाबेस उपयोगकर्ता

कोड-स्तर का सत्यापन महत्वपूर्ण है, लेकिन पर्याप्त नहीं है। सुरक्षा की अंतिम परत के रूप में डेटाबेस से ऐसे केवल-पठन वाले उपयोगकर्ता खाते के माध्यम से कनेक्ट करें जिसके पास केवल SELECT अनुमतियाँ हों। कोई दुर्भावनापूर्ण क्वेरी सभी जाँचों को पार कर जाए, तब भी डेटाबेस उसे अस्वीकार कर देगा।

# Create read-only user in PostgreSQL:
# CREATE USER nl_to_sql_reader WITH PASSWORD 'secure_password';
# GRANT CONNECT ON DATABASE yourdb TO nl_to_sql_reader;
# GRANT USAGE ON SCHEMA public TO nl_to_sql_reader;
# GRANT SELECT ON ALL TABLES IN SCHEMA public TO nl_to_sql_reader;

import os
import psycopg2

def get_readonly_connection():
    return psycopg2.connect(
        host=os.getenv('DB_HOST'),
        database=os.getenv('DB_NAME'),
        user='nl_to_sql_reader',       # read-only account
        password=os.getenv('DB_READER_PASS')
    )

ज्ञान जाँच

NL से एसक्यूएल एजेंट में एसक्यूएल सत्यापन के लिए रक्षा की अतिरिक्त परत वाला सही तरीका क्या है?

पुनरावलोकन: एसक्यूएल बनाना और सत्यापित करना

सुरक्षित एसक्यूएल बनाने के लिए पूरी सत्यापन प्रक्रिया आवश्यक है: LLM आउटपुट से स्वच्छ एसक्यूएल निकालें, sqlparse का उपयोग करके केवल SELECT लागू करें, कीवर्ड ब्लॉकलिस्ट लगाएँ, तालिका नामों का वास्तविक स्कीमा से मिलान करें, पंक्ति सीमाएँ लागू करें और अंतिम सुरक्षा उपाय के रूप में केवल-पठन वाले डेटाबेस उपयोगकर्ता का उपयोग करें।

उपयोगकर्ता द्वारा दिए गए मान शामिल होने पर पैरामीटरयुक्त क्वेरी इंजेक्शन से सुरक्षा देती हैं। EXPLAIN योजना की जाँच अनपेक्षित रूप से महँगी क्वेरी को उत्पादन डेटा पर चलने से रोकती है।

शुरुआत निःशुल्क

एआई शिक्षक के साथ AI एजेंट सीखें — निःशुल्क

अपने ब्राउज़र में वास्तविक कोड लिखें और चलाएँ, चौबीसों घंटे एआई शिक्षक से तुरंत सहायता पाएँ, और वेब या ऐप पर वहीं से शुरू करें जहाँ आपने छोड़ा था।

पाठ्यक्रम
60
पाठ
239

अक्सर पूछे जाने वाले प्रश्न

क्या “SQL क्वेरी बनाना और सत्यापित करना” पाठ निःशुल्क है?

हाँ—“SQL क्वेरी बनाना और सत्यापित करना” का पूरा पाठ यहाँ वेब पर निःशुल्क पढ़ा जा सकता है। इंटरैक्टिव अभ्यास (अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर) करने और AI एजेंट पाठ्यक्रम का बाकी हिस्सा अनलॉक करने के लिए CoddyKit PRO लें। AI एजेंट पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

“SQL क्वेरी बनाना और सत्यापित करना” में मैं क्या सीखूँगा?

सुरक्षित SQL के लिए प्रॉम्प्ट पैटर्न: केवल-SELECT मोड और पैरामीटरयुक्त क्वेरी। आप ब्राउज़र में सीधे चलाए जाने वाले व्यावहारिक कोड के साथ AI एजेंट का अभ्यास करते हैं, और पाठ पूरा करते समय 24/7 एआई ट्यूटर आपके प्रश्नों के उत्तर देता है।

क्या AI एजेंट शुरू करने के लिए मुझे किसी अनुभव की आवश्यकता है?

पहले के अनुभव की आवश्यकता नहीं है। CoddyKit पर AI एजेंट शुरुआती से लेकर उन्नत शिक्षार्थियों तक सभी के लिए व्यवस्थित किया गया है, इसलिए आप यहीं से या शुरुआत से सीखना शुरू कर सकते हैं और अपनी गति से आगे बढ़ सकते हैं। यह 4 में से 3वाँ पाठ है।

“SQL क्वेरी बनाना और सत्यापित करना” पाठ पूरा करने में कितना समय लगता है?

CoddyKit का अधिकांश पाठ लगभग 5–10 मिनट में पूरा हो जाता है। हर पाठ छोटा और संवादात्मक है, इसलिए आप लगातार प्रगति करते हैं और वेब या ऐप पर वहीं से सीखना जारी रख सकते हैं जहाँ आपने छोड़ा था।

क्या मैं इस AI एजेंट पाठ में कोड लिख और चला सकता हूँ?

हाँ। हर AI एजेंट पाठ में एक अंतर्निर्मित कोड संपादक शामिल है, जिससे आप सीधे अपने ब्राउज़र में वास्तविक कोड लिख और चला सकते हैं और तुरंत एआई प्रतिक्रिया पा सकते हैं—स्थानीय सेटअप की आवश्यकता नहीं है।

इस पाठ्यक्रम के सभी पाठ

  1. NL-to-SQL एजेंट कैसे काम करते हैं
  2. स्कीमा समझना और इंजेक्ट करना
  3. SQL क्वेरी बनाना और सत्यापित करना
  4. अस्पष्ट डेटाबेस प्रश्नों को संभालना
← AI एजेंट पर वापस जाएँ