Перейти к содержимому
Калькуляторы

Запрос Mysql выполненный на bash

Приветствую!

Дано: Mysql 4x, база данных base_name, таблица "users"

 

Надо:

Скрипт на bash, который из базы base_name делает выборку из таблицы "users" по заданному значению столбца "GID" (0-9), затем у попавших в выборку отнимает из столбца "deposit" определенное значение и соответственно записывает новые значения обратно.

 

Кто-то может изобразить здесь такой скрипт ?

Изменено пользователем DiM_TauRus

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Месье знает толк в извращениях. А чем Вас перл не устраивает?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

можно и перл. лишь бы работало.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

#!/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")

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Поскольку весь скрипт создается ради одного запроса, который к тому же не возвращает никаких данных, то самое оно его запускать как раз из шелл-скрипта, используя консольного клиента mysql. К сожалению, мускулем не пользуюсь уже несколько лет, всё больше постгрес да оракл, поэтому конкретно для мускула командную строку не приведу...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Поскольку весь скрипт создается ради одного запроса, который к тому же не возвращает никаких данных, то самое оно его запускать как раз из шелл-скрипта, используя консольного клиента mysql. К сожалению, мускулем не пользуюсь уже несколько лет, всё больше постгрес да оракл, поэтому конкретно для мускула командную строку не приведу...

Самое оно, если речь идет об одном апдейте. А вот если надо проводить сложные операции, то баш не поможет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Самое оно, если речь идет об одном апдейте. А вот если надо проводить сложные операции, то баш не поможет.

Сложные, это в такие, для которых даже sed/awk/cut/etc... не помогут а перл самое то? Кстати, условием ограничение на порождаемые процессы не было, так что шелл тоже катит.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Самое оно, если речь идет об одном апдейте. А вот если надо проводить сложные операции, то баш не поможет.

Сложные, это в такие, для которых даже sed/awk/cut/etc... не помогут а перл самое то? Кстати, условием ограничение на порождаемые процессы не было, так что шелл тоже катит.

Я понимаю, что можно шурупы и молотком забивать. Дайте пример, пожалуйста.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Я понимаю, что можно шурупы и молотком забивать. Дайте пример, пожалуйста.

Ну для примера неплохо бы увидеть ТЗ к этому примеру. Сформулируйте ТЗ - озвучу решение.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ну для примера неплохо бы увидеть ТЗ к этому примеру. Сформулируйте ТЗ - озвучу решение.
Скрипт на 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 на некоторое значение. Для красоты предположим даже, что значения лежат где-то в других таблицах, никакими джойнами их прицепить нельзя, поэтому для них тоже надо делать выборку. Вот ТЗ :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Спасибо люди!

 

Разобрался, интуитивно на основе приведенных примеров написал скрипт, получилось, после добавления пары модулей для перла.

 

Собственно скрипт нужен был для запихивания в крон с целью снятия абонплаты ).

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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 |
+------+----------+

Изменено пользователем GateKeeper

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

GateKeeper`у отдельное спасибо за полностью шеловый вариант, это и правда полезно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

2 GateKeeper

Красиво, хоть и сложновато. Если у меня под рукой не окажется перла, возьму на заметку Ваш вариант ;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Кстати, особо прошу обратить внимание на регекспы: мой катит только для случая, когда `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`

Изменено пользователем GateKeeper

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Гость
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Вставить в виде обычного текста

  Разрешено не более 75 смайлов.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.