Консультация № 180439
25.10.2010, 11:16
52.20 руб.
0 17 0
Здравствуйте уважаемые!

MySQL 5.0.18.
Нужно написать встроенную функцию, которая возвращает целочисленное значение, идентификатор, из заданной в параметрах таблицы и значения другого текстового поля. Должно получиться что-то типа того (это нужно для выборки):
Код:
SELECT t.name, MyFunction(t.name, 'НазваниеТаблицы') FROM тра-ля-ля...

Т.е. я вызываю в выборке функцию MyFunction с параметрами:
- некое строковое значение
- название таблицы из той же БД
и получаю в ответ идентификатор.
У меня вызывает затруднение, как в том операторе SELECT, который будет в функции, в качестве названия таблицы будет стоять параметр функции...

Обсуждение

Неизвестный
25.10.2010, 12:04
общий
sir Henry:
Для такой конструкции нужно использовать динамический SQL.
Вот тут описание для MySQL.
Надеюсь, поможет.
давно
Мастер-Эксперт
425
4118
25.10.2010, 12:14
общий
Абаянцев Юрий Леонидович aka Ayl:
Ого, какие сложности. Я думал, может что попроще будет.
Спасибо, сейчас почитаю.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
давно
Мастер-Эксперт
425
4118
25.10.2010, 12:35
общий
Абаянцев Юрий Леонидович aka Ayl:
Попробовал. Увы...
Получаю сообщение: "Dynamic SQL is not allowed in stored function or trigger"...
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Неизвестный
31.10.2010, 15:31
общий
sir Henry:
Может, стоит пересмотреть сам подход - идею?
на вскидку, подумал что можно как то так
Код:

CREATE or REPLACE FUNCTION fGetID(
sname CHAR(32),
stable CHAR(32)
)
RETURNS INT
BEGIN
SET @Y = 0;
SET @query = CONCAT('SELECT TAB_NUM FROM ',STABLE,' WHERE FAM = ',SNAME);
PREPARE stmt1 FROM @query;
EXECUTE stmt1 USING @Y;
DEALLOCATE PREPARE stmt1;
RETURN @Y;
END;


Но, во первых не думаю что это есть верно и будет работать, во вторых - я не сторонник таки извращений
Думаю, стоит пересмотреть все же идею.. Да и с точки оптимальности - не есть хорошо.
давно
Мастер-Эксперт
425
4118
31.10.2010, 15:51
общий
Victor Pyrlik:
Проблема в том, что Dynamic SQL в функциях MySQL не работает в принципе. По крайней мере в версии 5.0.18, которая стоит у меня. Я ведь подобную функцию сваял. Единственное чего от неё поступает - ошибка в моём предыдущем посте.
Если у тебя есть какая-нибудь идея - озвучь, а то я себе уже голову сломал.
Дело в том, что подобная функция должна применяться во всех командах SQL - SELECT, INSERT и UPDATE. Возможно и в DELETE тоже.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Неизвестный
31.10.2010, 17:11
общий
sir Henry:
Цитата: Вадим Исаев ака sir Henry
Дело в том, что подобная функция должна применяться во всех командах SQL - SELECT, INSERT и UPDATE. Возможно и в DELETE тоже.

Убери требование "разные, неизвестные таблицы".. и всё будет хокей.
У меня так же есть функции которые возвращают ID по номеру например или еще по какому параметру - но из конкретной таблицы, хотя, на Oracle это не сложно реализовать (о чем ты говоришь).

например:
Код:

UPDATE L2.HEAT_EAF E SET
E.HEAT_ID = GET_HEATID(E.HEAT_NUM);
COMMIT;

UPDATE L2.HEAT_VKM SET
CREW_ID = GET_CREWID(SYSDATE)
WHERE HEAT_ID = GET_HEATDATE(SYSDATE);
COMMIT;



давно
Мастер-Эксперт
425
4118
31.10.2010, 17:20
общий
Victor Pyrlik:
Цитата: 19206
Убери требование "разные, неизвестные таблицы".. и всё будет хокей.

Тогда вместо одной функции у меня будет их 32 с одним и тем же кодом.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Неизвестный
31.10.2010, 17:25
общий
sir Henry:
Сказал бы я.. на этот счет
Но, знаешь, возможно и стоит подумать и поломать голову.. Но, с точки зрения оптимальности - далеко не лучший выбор. Они так же будут отрабатывать для 32 таблиц..
Ну и.. есть вероятность, что не для всех таблиц будет код аналогичен.. (иначе - что-то странное в этом случае, 32 одинаковые таблицы)..
Нет, я считаю что всё же надо для каждой таблицы реализовать функцию..
давно
Мастер-Эксперт
425
4118
31.10.2010, 17:46
общий
Victor Pyrlik:
У всех этих таблиц, в числе прочих, есть два поля с одинаковыми именами. В целях унифификации... Соответственно и действия со всеми таблицами будут аналогичны - поиск идешника по соответствующему строковому значению.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Неизвестный
31.10.2010, 17:53
общий
sir Henry:
Поверь, далеко не всегда "унификация" есть добро.. Часто в порывах "оптимизировать" мы создаем себе гемо... в общем дискомфортное ощущение ниже спины
давно
Мастер-Эксперт
425
4118
31.10.2010, 17:57
общий
Victor Pyrlik:
Не тот случай.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Неизвестный
31.10.2010, 18:05
общий
sir Henry:
Конечно тебе видней.
Но, всегда, когда встают подобные вопросы - я спрашиваю, "а что, модель не удовлетворяет реляционной?".. У себя так же спрашиваю - когда вижу что начинаю что-то усложнять..
Моё мнение - твоё желание использовать динамические процедуры, не лучший вариант.. К тому же, у MySQL еще далеко не все так гладко с программированием в этом плане.

Но, дело твоё конечно. Потом просто может оказаться что зря убил мозг и время.. кроме сложностей ничего не получил. Да и "быстрей" это работать явно не будет, подозреваю что даже медленней и медленней..
Неизвестный
31.10.2010, 18:12
общий
sir Henry:
В твоём примере, вызов типа
SELECT t.name, MyFunction(t.name, 'НазваниеТаблицы') FROM тра-ля-ля...


Имеет смысл только, если 'НазваниеТаблицы' это поле, т.е. например так:

SELECT t.name, MyFunction(t.name, t.table_name) FROM тра-ля-ля...
и при этом, каждая строка возвращает разную таблицу..

Во всех остальных случаях, тот же JOIN может быть намного эффективней и гибче и проще и бысртрей.
давно
Мастер-Эксперт
425
4118
31.10.2010, 18:29
общий
Victor Pyrlik:
Цитата: 19206
твоё желание использовать динамические процедуры

Начнём с того, что использование динамики мне посоветовали здешние эксперты и ты в том числе. Я думал есть какой-нибудь более изящный и лёгкий способ, какая-нибудь особенность, которую я в MySQL не знаю.
Цитата: 19206
Во всех остальных случаях, тот же JOIN может быть намного эффективней и гибче и проще и бысртрей.

Если бы дело ограничивалось только SELECT'ом, я бы сразу JOIN и применил. Но я ведь и написал, что:
Цитата: Вадим Исаев ака sir Henry
подобная функция должна применяться во всех командах SQL - SELECT, INSERT и UPDATE. Возможно и в DELETE тоже.

согласись, никакой JOIN тут не поможет.
Я хочу чтобы применялась какая-то универсальная функция, чтобы не парить мозги с сотней разных названий.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Неизвестный
31.10.2010, 21:21
общий
sir Henry:
Цитата: Вадим Исаев ака sir Henry
согласись, никакой JOIN тут не поможет.

это почему?
Цитата: Вадим Исаев ака sir Henry
Начнём с того, что использование динамики мне посоветовали здешние эксперты и ты в том числе.

Цитата: Вадим Исаев ака sir Henry
Т.е. я вызываю в выборке функцию MyFunction с параметрами:

Ты как раз это и просил.. даже может и не подозревая
Ладно,
универсальная функция, чтобы не парить мозги
не в этом случае.. , жаль, что я не смог тебе помочь.
PS:даже боюсь представить, как люди убого жили на 4.х верcии MySQL . Грабли, они потому такие не прямые.. что бы на всех хватало
давно
Мастер-Эксперт
425
4118
01.11.2010, 03:07
общий
Victor Pyrlik:
Цитата: 19206
даже боюсь представить, как люди убого жили на 4.х верcии MySQL

Фигня делов то... У меня учёт трафика до сих пор работает на четвёрке.
Цитата: 19206
это почему?

Например вот почему:
Код:
INSERT INTO user_jornal SET user_id=(SELECT id FROM users_dict WHERE login='UserLogin')
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Неизвестный
01.11.2010, 08:52
общий
sir Henry:
Цитата: Вадим Исаев ака sir Henry
Выполняя чвою часть разработки БД я занялся журналированием посещения БД.

У меня фискальный журнал ведется на основании одной процедуры. Куда я передаю:
название объекта, операцию. - это всё строки, следовательно, в "операции" я могу указать что угодно, часто параметры (которые меня смущают)
В процедуре идет обычная вставка из селекта, идет дополнение: IP машины, Имя машины, Имя изверя, дата (timestamp), SID и т.д.
на выходе я вижу, что кто когда и где делал.

В таблицах что мне надо отслеживать в триггерах добавлен вызов SET_LOG(...).
Так же, натравлен триггер уровня БД с фильтром.

В общем то, аналогичное можно получить и в MySQL. А потому, тут надо не писать в "32 процедуры" или создавать "универсальную функцию" а создать обычную процедуру вставки в лог, и вызывать её откуда душе будет угодно
Форма ответа