Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / MySQL [игнор отключен] [закрыт для гостей] / вопрос о DUPLICATE KEY UPDATE / 16 сообщений из 16, страница 1 из 1
17.03.2015, 21:54:18
    #38907604
вадя
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос о DUPLICATE KEY UPDATE
INSERT
..... ON DUPLICATE KEY UPDATE

как можно узнать что было сделано?
INSERT или UPDATE?
last_insert_id не предлагать.
...
Рейтинг: 0 / 0
17.03.2015, 21:55:33
    #38907605
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос о DUPLICATE KEY UPDATE
вадяlast_insert_id не предлагать.что так?
...
Рейтинг: 0 / 0
17.03.2015, 22:18:41
    #38907617
вадя
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос о DUPLICATE KEY UPDATE
miksoftвадяlast_insert_id не предлагать.что так?
поля id (c его прибамбасами )нет
так нада... :)
...
Рейтинг: 0 / 0
17.03.2015, 22:23:40
    #38907619
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос о DUPLICATE KEY UPDATE
Если запись вставляется только одна (а не пачка), то last_insert_id все еще может помочь.
...
Рейтинг: 0 / 0
17.03.2015, 22:30:49
    #38907625
вадя
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос о DUPLICATE KEY UPDATE
miksoft,

у меня ast_insert_id всегда 0
...
Рейтинг: 0 / 0
17.03.2015, 22:46:19
    #38907637
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос о DUPLICATE KEY UPDATE
Ну можно запросить COUNT(*) до и после... а нах... зачем?
...
Рейтинг: 0 / 0
17.03.2015, 22:56:06
    #38907647
вадя
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос о DUPLICATE KEY UPDATE
для такова изврата :)
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
BEGIN
  SET @ip = INET_ATON('178.156.133.188');
  SET @x = 0;
  SET @login = 'user';
  SET @password = 'admin1';
  SET @pl = 0;
  SET @m = 0;
  SET @y = 0;
  INSERT INTO mo.access (ip, n, t)
    VALUE (@ip, 0, 0)
  ON DUPLICATE KEY UPDATE
  n = (SELECT
      @x := v.nn
    FROM (SELECT
        @a := UNIX_TIMESTAMP() - t,
        CASE WHEN @a < 10 THEN @m := n + 1 WHEN @a < 30 THEN @m := 3 WHEN @a >= 30 THEN @m := 0 END AS nn,
        CASE WHEN @m < 3 THEN @pl := (SELECT
                  COUNT(users.id) AS n
                FROM users
                WHERE users.login = @login
                AND users.password = @password) END,
        @y := 1
      FROM mo.access
      WHERE ip = @ip) AS v),
  t = CASE WHEN @x < 3 THEN UNIX_TIMESTAMP() ELSE t END;

  

  IF @y = 0 THEN
    SELECT
      COUNT(users.id) INTO @pl
    FROM users
    WHERE users.login = @login
    AND users.password = @password;
  END IF;


  SELECT
    @pl
  ;


но желательно избавиться от if в конце....
ну и упростиь, если можно...
...
Рейтинг: 0 / 0
18.03.2015, 02:48:46
    #38907731
Stupid_BOT
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос о DUPLICATE KEY UPDATE
авторно желательно избавиться от if в конце....
ну и упростиь, если можно...
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
  {skipped}
  INSERT INTO mo.access (ip, n, t)
  VALUES (@ip, 0, UNIX_TIMESTAMP())
  ON DUPLICATE KEY UPDATE
    n = @n:= CASE 
        WHEN (@a:= VALUES(t) - t) < 10 THEN n+1 
        WHEN @a < 30 THEN 3 
        ELSE 0 
    END,
    t = CASE 
        WHEN n < 3 THEN VALUES(t) 
        ELSE t 
    END;
  
  SET @p1:= CASE
      WHEN 1 = ROW_COUNT() OR @n < 3 THEN (
        SELECT COUNT(users.id)
        FROM users
        WHERE users.login = @login
        AND users.password = @password 
      )
      ELSE 0
  END;  
  SELECT @p1;

...
Рейтинг: 0 / 0
18.03.2015, 08:11:56
    #38907807
вадя
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос о DUPLICATE KEY UPDATE
Stupid_BOT,
этот вариант я делал. у него один дефект - сначала всегда происходит insert , а если ip новый то проверки на логин , пароль не происходит.
...
Рейтинг: 0 / 0
18.03.2015, 08:19:39
    #38907811
вадя
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос о DUPLICATE KEY UPDATE
вадя,
sory, с телефона не рассмотрел, предложенный вариант интересен, похож на мой - состоит их из двух частей, хочется из одной.
...
Рейтинг: 0 / 0
18.03.2015, 09:18:59
    #38907849
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос о DUPLICATE KEY UPDATE
вадя , было бы правильным не только показать код, но и разъяснить идею, которая за ним прячется.
На всякий случай вот тебе идея - работает даже для INSERT ... SELECT ... ON DUPLICATE KEY UPDATE ...

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
mysql> CREATE TABLE test (id INT PRIMARY KEY, val INT);
Query OK, 0 rows affected (0.18 sec)

mysql> INSERT INTO test (id,val)
    -> SELECT 1,1 UNION ALL
    -> SELECT 2,1 ;
Query OK, 2 rows affected (0.03 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM test;
+----+------+
| id | val  |
+----+------+
|  1 |    1 |
|  2 |    1 |
+----+------+
2 rows in set (0.05 sec)

mysql> DELIMITER |
mysql> CREATE TRIGGER au_test AFTER UPDATE ON test
    ->   FOR EACH ROW BEGIN
    ->     SET @upd = @upd  + 1;
    ->   END; |
Query OK, 0 rows affected (0.06 sec)

mysql> CREATE TRIGGER ai_test AFTER INSERT ON test
    ->   FOR EACH ROW BEGIN
    ->     SET @ins = @ins + 1;
    ->   END; |
Query OK, 0 rows affected (0.06 sec)

mysql> DELIMITER ;

mysql> SET @upd = 0;
Query OK, 0 rows affected (0.00 sec)

mysql> SET @ins = 0;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO test (id,val) VALUES (1,1) ON DUPLICATE KEY UPDATE val = val + 1;
Query OK, 2 rows affected (0.02 sec)

mysql> SELECT @upd, @ins;
+------+------+
| @upd | @ins |
+------+------+
|    1 |    0 |
+------+------+
1 row in set (0.00 sec)

mysql> SELECT * FROM test;
+----+------+
| id | val  |
+----+------+
|  1 |    2 |
|  2 |    1 |
+----+------+
2 rows in set (0.00 sec)

mysql> SET @upd = 0;
Query OK, 0 rows affected (0.00 sec)

mysql> SET @ins = 0;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO test (id,val) VALUES (3,1) ON DUPLICATE KEY UPDATE val = val + 1;
Query OK, 1 row affected (0.02 sec)

mysql> SELECT @upd, @ins;
+------+------+
| @upd | @ins |
+------+------+
|    0 |    1 |
+------+------+
1 row in set (0.00 sec)

mysql> SELECT * FROM test;
+----+------+
| id | val  |
+----+------+
|  1 |    2 |
|  2 |    1 |
|  3 |    1 |
+----+------+
3 rows in set (0.00 sec)

mysql> SET @upd = 0;
Query OK, 0 rows affected (0.00 sec)

mysql> SET @ins = 0;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO test (id,val)
    -> SELECT 1,1 UNION ALL
    -> SELECT 4,1
    -> ON DUPLICATE KEY UPDATE val = val + 1;
Query OK, 3 rows affected (0.03 sec)
Records: 2  Duplicates: 1  Warnings: 0

mysql> SELECT @upd, @ins;
+------+------+
| @upd | @ins |
+------+------+
|    1 |    1 |
+------+------+
1 row in set (0.00 sec)

mysql> SELECT * FROM test;
+----+------+
| id | val  |
+----+------+
|  1 |    3 |
|  2 |    1 |
|  3 |    1 |
|  4 |    1 |
+----+------+
4 rows in set (0.07 sec)
...
Рейтинг: 0 / 0
18.03.2015, 12:20:26
    #38908158
вадя
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос о DUPLICATE KEY UPDATE
Akina,
идея в том чтоб производить проверку логин/пароль и исключить подбор их . допускается три попытки в течении 10 сек, потом 30 сек игнорирования проверки, т.е. логин/пароль принимаютя, но не происходит запроса к базе, внешне это выглядит как будто всё проверяется.(времена пока с потолка, чтоб прверять не долго было). Мой вариант работает, но хочется проще ,за один запрос. в таблице n это число проделанных попыток.
...
Рейтинг: 0 / 0
18.03.2015, 12:25:38
    #38908168
вадя
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос о DUPLICATE KEY UPDATE
возвращает 1 если есть такой юзер , 0 в любом другом случае, даже если в 30 секундном интервеле введен правильный пароль/логин
...
Рейтинг: 0 / 0
18.03.2015, 13:01:26
    #38908245
вадя
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос о DUPLICATE KEY UPDATE
что за синтаксиис
WHEN (@a:= VALUES(t) - t) < 10 THEN n+1
я в мануалах не смог найти
...
Рейтинг: 0 / 0
18.03.2015, 13:09:15
    #38908260
tanglir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос о DUPLICATE KEY UPDATE
вадя,

про values - здесь

а данный фрагмент записывает в переменную @a разность между вставляемым и имевшимся значениями, и если она меньше 10, то возвращает n+1
...
Рейтинг: 0 / 0
19.03.2015, 22:44:03
    #38910481
вадя
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос о DUPLICATE KEY UPDATE
боле логичный вариант
даётся 3 попытки, после 3 не правильных попыток делается пауза в 30 секунд (можно любое время) в течении которого возвращается количество попыток (они же и записываются в n), в таблицу так же записывается время время последней не правильной попытки. при неправильных попытках (> 3) обращение к таблице юзеров не происходит, поэтому даже правильная попытка будет проигнорирована.
таблицу access можно сделать в памяти (только надо следить за её размером) и тогда перебор логин/пароль не будет сильно грузить железо.

таблица
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
CREATE TABLE access (
  ip int(12) UNSIGNED NOT NULL DEFAULT 0,
  n int(11) NOT NULL DEFAULT 0,
  t bigint(20) NOT NULL DEFAULT 0,
  PRIMARY KEY (ip),
  UNIQUE INDEX UK_access_ip (ip)
)
ENGINE = INNODB
AVG_ROW_LENGTH = 8192
CHARACTER SET utf8
COLLATE utf8_general_ci;



хранимка
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
CREATE DEFINER = 'root'@'localhost'
PROCEDURE mo.procedure1(IN ip varchar(15), IN login varchar(20), IN password varchar(20), OUT access int)
BEGIN

  SET @login = login;
  SET @password = `password`;
  SET @a = UNIX_TIMESTAMP();

  INSERT INTO access (ip, n, t)
    VALUE (INET_ATON(ip), 0, 0)
  ON DUPLICATE KEY UPDATE
  n = @access := CASE WHEN (n < 3) OR
        (@a - t) > 30 THEN CASE WHEN (SELECT
                  COUNT(users.id)
                FROM users
                WHERE users.login = @login
                AND users.password = @password) = 1 THEN 0 ELSE n + 1 END ELSE n + 1 END,
  t = CASE WHEN n >= 3 THEN @a ELSE 0 END;

  IF 1 = ROW_COUNT() THEN
    SELECT
      IF(COUNT(users.id) = 0, 1, 0) INTO @access
    FROM users
    WHERE users.login = @login
    AND users.password = @password;
  END IF;

  SET access = @access;

END

...
Рейтинг: 0 / 0
Форумы / MySQL [игнор отключен] [закрыт для гостей] / вопрос о DUPLICATE KEY UPDATE / 16 сообщений из 16, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]