Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Можно ли написать на SQL программу?
Прямой ответ: ДА, МОЖНО, НО РЕДКО НУЖНО
Technically, SQL это язык программирования (Turing-complete в некоторых реализациях), но на нём редко пишут полноценные программы. Однако некоторые СУБД позволяют писать довольно сложную логику прямо в SQL или через расширения.
SQL как язык программирования
SQL - это не просто язык запросов, это полноценный язык с:
- Переменными
- Циклами
- Условиями
- Функциями
- Структурированной обработкой данных
-- PostgreSQL: PL/pgSQL - встроенный язык программирования
CREATE FUNCTION calculate_salary(employee_id INT)
RETURNS NUMERIC AS $$
DECLARE
base_salary NUMERIC;
bonus NUMERIC;
total NUMERIC;
BEGIN
-- Выборка данных
SELECT salary INTO base_salary
FROM employees
WHERE id = employee_id;
-- Условная логика
IF base_salary > 50000 THEN
bonus := base_salary * 0.15;
ELSIF base_salary > 30000 THEN
bonus := base_salary * 0.10;
ELSE
bonus := base_salary * 0.05;
END IF;
-- Вычисление
total := base_salary + bonus;
-- Возврат результата
RETURN total;
END;
$$ LANGUAGE plpgsql;
-- Использование
SELECT calculate_salary(1) AS employee_salary;
Способ 1: Хранимые процедуры (Stored Procedures)
-- MySQL: простая хранимая процедура
DELIMITER $$
CREATE PROCEDURE transfer_money(
FROM_ACCOUNT INT,
TO_ACCOUNT INT,
AMOUNT DECIMAL(10, 2)
)
BEGIN
DECLARE balance DECIMAL(10, 2);
START TRANSACTION;
-- Проверка баланса
SELECT current_balance INTO balance
FROM accounts
WHERE id = FROM_ACCOUNT
FOR UPDATE;
IF balance >= AMOUNT THEN
-- Снять с первого счёта
UPDATE accounts
SET current_balance = current_balance - AMOUNT
WHERE id = FROM_ACCOUNT;
-- Добавить на второй счёт
UPDATE accounts
SET current_balance = current_balance + AMOUNT
WHERE id = TO_ACCOUNT;
COMMIT;
SELECT 'Transfer successful' AS result;
ELSE
ROLLBACK;
SELECT 'Insufficient funds' AS error;
END IF;
END$$
DELIMITER ;
-- Вызов
CALL transfer_money(1, 2, 100.50);
Способ 2: Триггеры (Triggers)
-- PostgreSQL: триггер для логирования
CREATE TABLE audit_log (
id SERIAL PRIMARY KEY,
table_name TEXT,
operation TEXT,
old_data JSONB,
new_data JSONB,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE FUNCTION log_changes()
RETURNS TRIGGER AS $$
BEGIN
IF TG_OP = 'DELETE' THEN
INSERT INTO audit_log (table_name, operation, old_data)
VALUES (TG_TABLE_NAME, TG_OP, row_to_json(OLD));
ELSIF TG_OP = 'UPDATE' THEN
INSERT INTO audit_log (table_name, operation, old_data, new_data)
VALUES (TG_TABLE_NAME, TG_OP, row_to_json(OLD), row_to_json(NEW));
ELSIF TG_OP = 'INSERT' THEN
INSERT INTO audit_log (table_name, operation, new_data)
VALUES (TG_TABLE_NAME, TG_OP, row_to_json(NEW));
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER users_audit
AFTER INSERT OR UPDATE OR DELETE ON users
FOR EACH ROW
EXECUTE FUNCTION log_changes();
Способ 3: Рекурсивные запросы (CTE)
-- Вычисление факториала на SQL
WITH RECURSIVE factorial AS (
-- Base case
SELECT 1 AS n, 1 AS result
UNION ALL
-- Recursive case
SELECT n + 1, result * (n + 1)
FROM factorial
WHERE n < 5 -- Условие выхода из рекурсии
)
SELECT * FROM factorial;
-- Результат:
-- n | result
-- 1 | 1
-- 2 | 2
-- 3 | 6
-- 4 | 24
-- 5 | 120
Способ 4: Сложные вычисления с циклами
-- PostgreSQL: вычисление рядов
CREATE FUNCTION fibonacci(n INT)
RETURNS INT AS $$
DECLARE
a INT := 0;
b INT := 1;
i INT;
temp INT;
BEGIN
FOR i IN 1..n LOOP
temp := a + b;
a := b;
b := temp;
END LOOP;
RETURN a;
END;
$$ LANGUAGE plpgsql;
SELECT fibonacci(10); -- Результат: 55
Способ 5: Обработка текста и строк
-- PostgreSQL: работа со строками
CREATE FUNCTION reverse_string(input_str TEXT)
RETURNS TEXT AS $$
DECLARE
result TEXT := '';
i INT;
BEGIN
FOR i IN REVERSE LENGTH(input_str)..1 LOOP
result := result || SUBSTR(input_str, i, 1);
END LOOP;
RETURN result;
END;
$$ LANGUAGE plpgsql;
SELECT reverse_string('Hello'); -- Результат: olleH
Почему редко пишут полные программы на SQL?
- Плохая читаемость - SQL не очень удобен для сложной логики
- Отсутствие стандартизации - каждая СУБД своя синтаксис
- Ограниченные возможности - нет легкого доступа к сетевым операциям, файловой системе
- Сложность отладки - трудно отлаживать логику в БД
- Производительность - иногда медленнее чем в приложении
# Вместо этого пишут на Python с использованием SQL:
import sqlite3
def transfer_money(from_account, to_account, amount):
conn = sqlite3.connect(':memory:')
cursor = conn.cursor()
try:
# Логика обработки ошибок в Python
balance = cursor.execute(
'SELECT balance FROM accounts WHERE id = ?',
(from_account,)
).fetchone()[0]
if balance >= amount:
cursor.execute(
'UPDATE accounts SET balance = balance - ? WHERE id = ?',
(amount, from_account)
)
cursor.execute(
'UPDATE accounts SET balance = balance + ? WHERE id = ?',
(amount, to_account)
)
conn.commit()
return True
except Exception as e:
conn.rollback()
raise
finally:
conn.close()
Когда всё же используют SQL-программы?
- Триггеры - для автоматических действий при изменении данных
- Хранимые процедуры - для сложных операций с данными в БД
- Представления (Views) - для часто используемых запросов
- Check constraints - для валидации данных
Вывод
Технически на SQL можно написать полноценную программу с условиями, циклами и функциями. Однако на практике SQL используется для:
- Запросов к данным - основное применение
- Хранимых процедур - сложная логика в БД
- Триггеров - автоматизация действий
Для полноценной разработки приложений SQL комбинируют с языками программирования (Python, Java, JavaScript и т.д.), где логика читаема и легче поддерживается.