Возможно ли в MySQL извлечь результат вычисления выражения, содержащегося в строке?

В моем столбце содержатся формулы в формате = 3*(USD)+2. У меня есть функция, которая подставляет текущий курс, и в результате выполнения SELECT calc_formula_usd_byn(formula) я получаю строку '3*0.30+2'. Однако, в MySQL функции нельзя динамически вычислить результат. Как можно решить эту проблему?
  • 29 октября 2024 г. 11:02
Ответы на вопрос 2
В MySQL вы действительно не можете динамически вычислять строки как код SQL, так как это может представлять собой серьезную проблему с безопасностью. Однако есть несколько подходов, которые вы можете использовать, чтобы обойти это ограничение.

### 1. Использование хранимых процедур

Вы можете создать хранимую процедуру, которая принимает формулу в виде строки и заменяет значения в формуле на фактические значения. Затем вы можете выполнить выражение с использованием динамического SQL.

Пример:

```sql
DELIMITER //

CREATE PROCEDURE CalculateFormula(IN formula VARCHAR(255), IN rate DECIMAL(10, 2), OUT result DECIMAL(10, 2))
BEGIN
    SET @query = REPLACE(formula, 'USD', rate);
    SET @query = REPLACE(@query, '=', '');  -- Убираем символ равенства, если есть
    SET @query = CONCAT('SELECT ', @query);
    
    PREPARE stmt FROM @query;
    EXECUTE stmt INTO result;
    DEALLOCATE PREPARE stmt;
END //

DELIMITER ;
```

Вызов процедуры через `CALL`:

```sql
CALL CalculateFormula('= 3*USD + 2', 0.30, @result);
SELECT @result;
```

### 2. Выполнение в приложении

Если у вас есть доступ к приложению, вы можете извлекать данные из базы данных с формулами, затем обрабатывать формулы на стороне приложения. Это даст больше гибкости и безопасности.

Пример на Python:

```python
import sqlite3  # или другой драйвер для MySQL

# Получите формулу из базы данных
cursor.execute("SELECT formula FROM your_table WHERE id = ?", (some_id,))
formula = cursor.fetchone()[0]

# Замените USD на его значение
rate = 0.30
eval_formula = formula.replace('USD', str(rate)).replace('=', '')

# Вычислите результат
result = eval(eval_formula)
```

Избегайте использования `eval` с неопознанным вводом, так как это может быть небезопасно.

### 3. Реализация простого парсера формул

Если ваши формулы достаточно просты, вы можете реализовать базовый парсер выражений с поддержкой основных операций. Примеры библиотек, которые могут помочь, включают `parse` или `numpy` для Python.

---

Каждый из этих подходов имеет свои преимущества и недостатки, и лучший выбор зависит от ваших конкретных потребностей и контекста, в котором вы работаете.
Используй динамические запросы, напиши с помощью create function свою, в которой с помощью prepare и execute исполняй sql запрос, собираемый из твоей строки в таблицу плюс добавив нужные таблицы, потребность в таблицах нужно будет как то вычислять, анализируя выражение, либо задавать дополнительным полем (рекомендую этот анализ и формирование динамического sql запроса выполнять в тригерах или отдельным вызовом, который ты будешь вызывать после обновления своих формул), вот пример если используются только одна таблица, а логика фильтрации в ней заранее понятна: 
set sql=concat('select ',expr,' into @result from my_table where id=',id)
prepare stmt from sql;
execute stmt;
deallocate prepare stmt;
set result = @result;
return result;

в этом случае expr будет в формате sql а имена переменных из таблицы

Если таблиц будет несколько, то добавляй имена таблиц, а анализ запроса делай через поиск " имя_таблицы. " и делай соответствующий join и фильтрацию по индексам foreign и primary key (не советую делать мега алгоритм, разбирающий всю базу по структурам, хотя если запилишь, будет наверное мощная и полезная система, скорее всего у тебя будет 2-3 запроса, и нужно будет только понять, когда какой использовать)
Похожие вопросы