Jump to content

Recommended Posts

Posted (edited)

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

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

 

Надо:

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

 

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

Edited by DiM_TauRus
Posted

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

Posted

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

Posted

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

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

Posted

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

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

Posted

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

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

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

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

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

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

Posted

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

 

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

 

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

Posted (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 by GateKeeper
Posted (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 by GateKeeper

Join the conversation

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

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...
На сайте используются файлы cookie и сервисы аналитики для корректной работы форума и улучшения качества обслуживания. Продолжая использовать сайт, вы соглашаетесь с использованием файлов cookie и с Политикой конфиденциальности.