DiM_TauRus Posted January 15, 2007 Posted January 15, 2007 (edited) Приветствую! Дано: Mysql 4x, база данных base_name, таблица "users" Надо: Скрипт на bash, который из базы base_name делает выборку из таблицы "users" по заданному значению столбца "GID" (0-9), затем у попавших в выборку отнимает из столбца "deposit" определенное значение и соответственно записывает новые значения обратно. Кто-то может изобразить здесь такой скрипт ? Edited January 15, 2007 by DiM_TauRus Вставить ник Quote
EvilShadow Posted January 16, 2007 Posted January 16, 2007 Месье знает толк в извращениях. А чем Вас перл не устраивает? Вставить ник Quote
DiM_TauRus Posted January 16, 2007 Author Posted January 16, 2007 можно и перл. лишь бы работало. Вставить ник Quote
EvilShadow Posted January 16, 2007 Posted January 16, 2007 #!/usr/bin/perl use DBI; my $sql_db = "db"; my $sql_user = "user"; my $sql_pass = "pass"; my $dbh = DBI->connect("DBI:mysql:$db", $sql_user, $sql_pass); my $gid_value = 1; my $query = qq { SELECT gid, deposit FROM users WHERE gid=$gid_value }; my $sth = $dbh->prepare ($query); $sth->execute (); while (my $row = $sth->fetchrow_hashref()) { $dbh->do ("UPDATE user SET deposit=deposit-$deposit_minus_var where gid=$row->{gid}"); } Впрочем, можно и проще, если вычитаемая сумма одинакова или может быть вычислена на основании др. таблиц: #!/usr/bin/perl use DBI; my $sql_db = "db"; my $sql_user = "user"; my $sql_pass = "pass"; my $dbh = DBI->connect("DBI:mysql:$db", $sql_user, $sql_pass); $dbh->do ("UPDATE users SET deposit=deposit-$sum WHERE gid=$gid_value") Вставить ник Quote
Kuzmich Posted January 16, 2007 Posted January 16, 2007 Поскольку весь скрипт создается ради одного запроса, который к тому же не возвращает никаких данных, то самое оно его запускать как раз из шелл-скрипта, используя консольного клиента mysql. К сожалению, мускулем не пользуюсь уже несколько лет, всё больше постгрес да оракл, поэтому конкретно для мускула командную строку не приведу... Вставить ник Quote
EvilShadow Posted January 16, 2007 Posted January 16, 2007 Поскольку весь скрипт создается ради одного запроса, который к тому же не возвращает никаких данных, то самое оно его запускать как раз из шелл-скрипта, используя консольного клиента mysql. К сожалению, мускулем не пользуюсь уже несколько лет, всё больше постгрес да оракл, поэтому конкретно для мускула командную строку не приведу... Самое оно, если речь идет об одном апдейте. А вот если надо проводить сложные операции, то баш не поможет. Вставить ник Quote
GateKeeper Posted January 16, 2007 Posted January 16, 2007 Самое оно, если речь идет об одном апдейте. А вот если надо проводить сложные операции, то баш не поможет. Сложные, это в такие, для которых даже sed/awk/cut/etc... не помогут а перл самое то? Кстати, условием ограничение на порождаемые процессы не было, так что шелл тоже катит. Вставить ник Quote
EvilShadow Posted January 16, 2007 Posted January 16, 2007 Самое оно, если речь идет об одном апдейте. А вот если надо проводить сложные операции, то баш не поможет.Сложные, это в такие, для которых даже sed/awk/cut/etc... не помогут а перл самое то? Кстати, условием ограничение на порождаемые процессы не было, так что шелл тоже катит. Я понимаю, что можно шурупы и молотком забивать. Дайте пример, пожалуйста. Вставить ник Quote
GateKeeper Posted January 16, 2007 Posted January 16, 2007 Я понимаю, что можно шурупы и молотком забивать. Дайте пример, пожалуйста. Ну для примера неплохо бы увидеть ТЗ к этому примеру. Сформулируйте ТЗ - озвучу решение. Вставить ник Quote
EvilShadow Posted January 16, 2007 Posted January 16, 2007 Ну для примера неплохо бы увидеть ТЗ к этому примеру. Сформулируйте ТЗ - озвучу решение. Скрипт на bash, который из базы base_name делает выборку из таблицы "users" по заданному значению столбца "GID" (0-9), затем у попавших в выборку отнимает из столбца "deposit" определенное значение и соответственно записывает новые значения обратно.Простейший случай - когда вычитаемая сумма постоянна, то mysql -uuser -ppassword database -e 'UPDATE users SET deposit=deposit-_sum_ WHERE gid=_gid_' Но мы его не рассматриваем :) Предположим, что в SQL-запросе выполнить все действия нельзя. Есть awk/cut/sed и т.д. Нужно сделать буквально то, что указано в задаче, а именно - сделать выборку (обязательно) и для каждого gid из выборки изменить deposit на некоторое значение. Для красоты предположим даже, что значения лежат где-то в других таблицах, никакими джойнами их прицепить нельзя, поэтому для них тоже надо делать выборку. Вот ТЗ :) Вставить ник Quote
DiM_TauRus Posted January 17, 2007 Author Posted January 17, 2007 Спасибо люди! Разобрался, интуитивно на основе приведенных примеров написал скрипт, получилось, после добавления пары модулей для перла. Собственно скрипт нужен был для запихивания в крон с целью снятия абонплаты ). Вставить ник Quote
GateKeeper Posted January 17, 2007 Posted January 17, 2007 (edited) table1 - таблица с gid вида: gid int(4), deposit double(16,4). table2 - таблица с некоторыми исходными данными по каждому gid (тарифы?) вида: gid int(4), decr_mult double(4,4), decr_const double(4,2). Надо: по каждому table1.gid провести уменьшение table1.deposit по формуле: table1.deposit = table1.deposit - table2.decr_const*table2.decr_mult, при этом данные из таблицы table2 брать в соответствии с gid. Ну и дополнительно: никоим образом при всём желании делать это одним запросом нельзя. Итак: #!/bin/sh M_HOST='localhost' M_USER='root' M_DB='ddd' M_PASS='derpassword' M_PARAMSTR="-h ${M_HOST} -u${M_USER} -p${M_PASS} -B $M_DB" echo "SELECT * FROM table2" | mysql ${M_PARAMSTR} > /tmp/defines.tbl echo "SELECT * FROM table1" | mysql ${M_PARAMSTR} | tail -n +2 | while read DEPROW; do DEP_GID=$(echo ${DEPROW} | cut -d " " -f 1) DEP_LASTVAL="$(echo ${DEPROW} | cut -d " " -f 2)" D_CONST="$(grep -E "^${DEP_GID}" /tmp/defines.tbl | cut -f 3)" || D_CONST="0" [ "$D_CONST" != "0" ] && D_MULT="$(grep -E "^${DEP_GID}" /tmp/defines.tbl | cut -f 2)" || D_MULT="0" if [ "$D_CONST" != "0" ] && [ "$D_MULT" != "0" ]; then DEP_NEWVAL="$(echo "${DEP_LASTVAL}-${D_CONST}*${D_MULT}" | bc)" echo "UPDATE table1 SET deposit = '${DEP_NEWVAL}' WHERE gid = '${DEP_GID}'" | mysql $M_PARAMSTR; fi; done; rm /tmp/defines.tbl Не спорю, что немного изврат для периодических снятий абонентки, однако если по условию "только на шелле" - оно самое. Главное, что в системе как правило всё для этого есть - и разные строковые обработчики (cut, grep) и математический процессор, работающий с дробными числами (bc) и т.д. По скрипту получилось: исходные данные: mysql> select * from table1; +------+----------+ | gid | deposit | +------+----------+ | 1 | 360.0000 | | 2 | 400.0000 | +------+----------+ mysql> select * from table2; +------+-----------+------------+ | gid | decr_mult | decr_const | +------+-----------+------------+ | 1 | 0.2500 | 50.00 | | 2 | 0.5000 | 50.00 | +------+-----------+------------+ после выполнения: mysql> select * from table1; +------+----------+ | gid | deposit | +------+----------+ | 1 | 347.5000 | | 2 | 375.0000 | +------+----------+ Edited January 17, 2007 by GateKeeper Вставить ник Quote
DiM_TauRus Posted January 17, 2007 Author Posted January 17, 2007 GateKeeper`у отдельное спасибо за полностью шеловый вариант, это и правда полезно. Вставить ник Quote
EvilShadow Posted January 17, 2007 Posted January 17, 2007 2 GateKeeper Красиво, хоть и сложновато. Если у меня под рукой не окажется перла, возьму на заметку Ваш вариант ;) Вставить ник Quote
GateKeeper Posted January 18, 2007 Posted January 18, 2007 (edited) Кстати, особо прошу обратить внимание на регекспы: мой катит только для случая, когда `0 <= gid <= 9`. Если строку: [ "$D_CONST" != "0" ] && D_MULT="$(grep -E "^${DEP_GID}" /tmp/defines.tbl | cut -f 2)" || D_MULT="0" заменить на: [ "$D_CONST" != "0" ] && D_MULT="$(grep -E "^${DEP_GID}[^[:digit:]]" /tmp/defines.tbl | cut -f 2)" || D_MULT="0" тогда прокатит для `gid >= 0` Edited January 18, 2007 by GateKeeper Вставить ник Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.