powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Вопрос по инкременту в MyISAM
23 сообщений из 23, страница 1 из 1
Вопрос по инкременту в MyISAM
    #39636521
systistrator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ответ наверное лежит на поверхности, но найти для себя я не могу. Ниже указал кусок из документации по auto increment, все в целом хорошо, но у меня возник вопрос, как при такой индексации можно вернуть уникальное значение id, не лишаясь конечно составного.

CREATE TABLE animals (
grp ENUM('fish','mammal','bird') NOT NULL,
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (grp,id)
) ENGINE=MyISAM;

INSERT INTO animals (grp,name) VALUES
('mammal','dog'),('mammal','cat'),
('bird','penguin'),('fish','lax'),('mammal','whale'),
('bird','ostrich');

SELECT * FROM animals ORDER BY grp,id;
Which returns:

+--------+----+---------+
| grp | id | name |
+--------+----+---------+
| fish | 1 | lax |
| mammal | 1 | dog |
| mammal | 2 | cat |
| mammal | 3 | whale |
| bird | 1 | penguin |
| bird | 2 | ostrich |
+--------+----+---------+
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39636532
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вопрос совершенно непонятен.
systistratorкак при такой индексации можно вернуть уникальное значение id, не лишаясь конечно составного.При такой структуре id НЕ УНИКАЛЕН . Уникален первичный ключ (grp,id).
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39636543
systistrator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вопрос в целом в том, как при такой конструкции получить уникальный код записи.
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39636547
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если нужен синтетический уникальный ID и нумерация внутри группы - делай две таблицы:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
CREATE TABLE animals (id SERIAL
                    , name VARCHAR(32)
                    , PRIMARY KEY (id)
                     )  ENGINE=MyISAM;
CREATE TABLE animal_groups (grp ENUM('fish','mammal','bird') NOT NULL
                          , id MEDIUMINT NOT NULL AUTO_INCREMENT
                          , animal_id BIGINT NOT NULL
                          , PRIMARY KEY (grp,id)
                          , FOREIGN KEY (animal_id) REFERENCES animals (id)
                           )  ENGINE=MyISAM;
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39636700
tip78
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AkinaЕсли нужен синтетический уникальный ID и нумерация внутри группы - делай две таблицы:
а что в mysql ограничение на кол-во auto-колонок в одной таблице?
так то можно просто id2-колонку сделать
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39636742
Melkij
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tip78а что в mysql ограничение на кол-во auto-колонок в одной таблице?
А разве нет?
There can be only one AUTO_INCREMENT column per table, it must be indexed, and it cannot have a DEFAULT value
Даже в свежей восьмёрке
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39636783
tip78
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
хм, не предусмотрели
пж вот предусмотрел
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39637397
systistrator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Учитывая, что в проекте таких групповых идентификаторов в рамках таблиц будет много решил воспользоваться своим опытам VFP... Да и если честно не хотелось бы использовать MyISAM.

1. Создать таблицу инкрементов
Код: sql
1.
2.
3.
4.
5.
6.
CREATE TABLE b_inc (
     id MEDIUMINT NOT NULL AUTO_INCREMENT,
     id_tbl CHAR(30) NOT NULL,
     inc MEDIUMINT NOT NULL, 
     PRIMARY KEY (id)
);



2. Написать функцию MySQL
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
DELIMITER // 
DROP FUNCTION IF EXISTS setAutoInc // 
CREATE FUNCTION setAutoInc (ID_VAR CHAR(50)) RETURNS INT 
BEGIN 
DECLARE cur_var INTEGER; 
SET cur_var = (SELECT inc FROM b_inc WHERE id_tbl = ID_VAR); 
IF  cur_var = NULL THEN 
INSERT INTO b_inc (id_tbl,inc) VALUES (ID_VAR,1) 
SET cur_var = 1; 
ELSE 
UPDATE b_inc SET inc = cur_var + 1 WHERE id_tbl = ID_VAR; 
END IF; 
RETURN cur_var + 1; 
END 
// 
DELIMITER ; 


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ответ MySQL: Документация
#1064 - У вас ошибка в запросе. Изучите документацию по используемой версии MySQL на предмет корректного синтаксиса около 'SET cur_var = 1;
ELSE
UPDATE b_inc SET inc = cur_var + 1 WHERE id_tbl = ID_VAR' на строке 7

***************
3. Создать триггер в таблице, который бы вызывал функцию и записывал искомое значение
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
DELIMITER // 
DROP TRIGGER IF EXISTS `gen_grp_id` // 
CREATE TRIGGER `gen_grp_id` AFTER INSERT ON `b` FOR EACH ROW 
BEGIN 
SET @inc = (SELECT SetAutoInc(CONCAT('B#',NEW._to,'#',NEW._year)); 
NEW.id_grp = @inc; 
END// 
DELIMITER ; 


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ошибка
Ответ MySQL: Документация
#1064 - У вас ошибка в запросе. Изучите документацию по используемой версии MySQL на предмет корректного синтаксиса около ';
NEW.id_grp = @inc;
END' на строке 3


Но вот незадача..., убил весь день в этих 10 строчках, но так и не понял по какой причине ошибки...
И вообще на сколько такое решение имеет право на существование, с чем я могу столкнуться?

Большое спасибо!
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39637429
tip78
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
там может SELECT INTO @inc какой-нить есть
в PG так: SELECT * INTO myrec FROM tbl WHERE id = 1;

да разломайте вы свой недоиндекс "PRIMARY KEY (grp,id)" и сделайте 1 - по ID
во1, grp + id должен быть id + grp, потому что уникальных ID куда больше, чем grp. Т.е. по grp он найдёт триллионы ID, по которым ему снова искать. А вот если по ID, то всего 3 группы.
во2, вам вообще индекс на grp не нужен, потому что их всего 3 будет!
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39637442
tip78
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
циферки подсчёта в каждой группе можно при селекте выводить
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39637461
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
systistrator2. Написать функцию MySQL
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
DELIMITER // 
DROP FUNCTION IF EXISTS setAutoInc // 
CREATE FUNCTION setAutoInc (ID_VAR CHAR(50)) RETURNS INT 
BEGIN 
DECLARE cur_var INTEGER; 
SET cur_var = (SELECT inc FROM b_inc WHERE id_tbl = ID_VAR); 
IF  cur_var = NULL THEN 
INSERT INTO b_inc (id_tbl,inc) VALUES (ID_VAR,1) 
SET cur_var = 1; 
ELSE 
UPDATE b_inc SET inc = cur_var + 1 WHERE id_tbl = ID_VAR; 
END IF; 
RETURN cur_var + 1; 
END 
// 
DELIMITER ; 



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ответ MySQL: Документация
#1064 - У вас ошибка в запросе. Изучите документацию по используемой версии MySQL на предмет корректного синтаксиса около 'SET cur_var = 1;
ELSE
UPDATE b_inc SET inc = cur_var + 1 WHERE id_tbl = ID_VAR' на строке 7
Пропущена точка с запятой в предыдущем операторе INSERT INTO.

systistrator3. Создать триггер в таблице, который бы вызывал функцию и записывал искомое значение
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
DELIMITER // 
DROP TRIGGER IF EXISTS `gen_grp_id` // 
CREATE TRIGGER `gen_grp_id` AFTER INSERT ON `b` FOR EACH ROW 
BEGIN 
SET @inc = (SELECT SetAutoInc(CONCAT('B#',NEW._to,'#',NEW._year)); 
NEW.id_grp = @inc; 
END// 
DELIMITER ; 



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ошибка
Ответ MySQL: Документация
#1064 - У вас ошибка в запросе. Изучите документацию по используемой версии MySQL на предмет корректного синтаксиса около ';
NEW.id_grp = @inc;
END' на строке 3
Используйте для присвоения значения переменной из запроса не SET, а SELECT .. INTO.
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39637463
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AkinaИспользуйте для присвоения значения переменной из запроса не SET, а SELECT .. INTO.Впрочем, в данном конкретном случае можно использовать прямое присвоение, без всяких SELECT.
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39637582
systistrator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
tip78циферки подсчёта в каждой группе можно при селекте выводить
Задача иная, мне нужен не подсчет строк, а именно инкремент в рамках определенного ключи. А при простом подсчете соответственно не будут учтены удаленные записи.

tip78да разломайте вы свой недоиндекс "PRIMARY KEY (grp,id)" и сделайте 1 - по ID
Да я его уже разломал... :)) Та, схема которую я сегодня пытаюсь победить сделана на InnoDB.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
CREATE TABLE `b` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `id_grp` int(11) NOT NULL,
  `_to` int(11) NOT NULL,
  `_year` int(4) NOT NULL,
  `name` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `b`
  ADD PRIMARY KEY (`id`),
  ADD KEY `_to` (`_to`),
  ADD KEY `_year` (`_year`),
  ADD KEY `id_grp` (`id_grp`);



В целом смысл в том, что есть таблица документов, в таблице есть _to (офис) и _year (год), у каждого офиса в рамках года должна быть своя нумерация. Сразу скажу, что создавать для каждого офиса свою таблицу не вариант, конечно конкретно в этом случае это можно было бы сделать (пришлось бы каждый год создавать 36 новых таблиц), но в рамках этого же проекта есть схожая задача, так там мне придется создавать 36*X (Х неизвестен) таблиц каждый день, да ещё в определенное время суток, в зависимости от часового пояса. Вообщем ищу более простой способ ))

AkinaПропущена точка с запятой в предыдущем операторе INSERT INTO.
Низкий поклон! Постараюсь быть внимательнее... Проверял все на 10 раз и такая оплошность...

Поправил, получилось :))

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
DELIMITER // 
DROP FUNCTION IF EXISTS setAutoInc // 
CREATE FUNCTION setAutoInc (ID_VAR CHAR(50)) RETURNS INT 
BEGIN 
DECLARE cur_var INTEGER; 
SET cur_var = (SELECT inc FROM b_inc WHERE id_tbl = ID_VAR); 
IF  (cur_var IS NULL) THEN 
INSERT INTO b_inc (id_tbl,inc) VALUES (ID_VAR,1);
RETURN 1; 
ELSE 
UPDATE b_inc SET inc = cur_var + 1 WHERE id_tbl = ID_VAR; 
END IF; 
RETURN cur_var + 1; 
END 
// 
DELIMITER ; 



mysql> select setAutoInc('02');
+------------------+
| setAutoInc('02') |
+------------------+
| 4 |
+------------------+
1 row in set (0.03 sec)

А вот с триггером у меня что-то плохо...

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
DELIMITER // 
DROP TRIGGER IF EXISTS `gen_grp_id` // 
CREATE TRIGGER `gen_grp_id` AFTER INSERT ON `b` FOR EACH ROW 
BEGIN 
DECLARE inc INT;
SELECT setAutoInc('01') INTO inc;
SELECT setAutoInc(CONCAT('B#',NEW._to,'#',NEW._year)) INTO inc;
SET @inc = (SELECT setAutoInc('01'));
NEW.id_grp = inc; 
END// 
DELIMITER ; 


Не через SELECT ... INTO, ни через SET не могу запустить.

Пишет:
Ответ MySQL: Документация

#1064 - У вас ошибка в запросе. Изучите документацию по используемой версии MySQL на предмет корректного синтаксиса около '.id_grp = inc;
END' на строке 6

Ну и вообще такая схема имеет права на существование?

Спасибо!
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39637653
tip78
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
systistratortip78циферки подсчёта в каждой группе можно при селекте выводить
Задача иная, мне нужен не подсчет строк, а именно инкремент в рамках определенного ключи. А при простом подсчете соответственно не будут учтены удаленные записи.
а для этого логи надо вести ;)

`_year` int(4) NOT NULL,
под год сгодится и tinyint unsigned
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39637656
tip78
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
systistratorА вот с триггером у меня что-то плохо...
что за дичь, почему вот так то нельзя?
Код: sql
1.
INSERT INTO tbl (grp,name,cnt) VALUES (1,2,(SELECT (max(cnt) +1) AS cnt FROM tbl WHERE grp = 'fish'))
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39637666
systistrator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сделал так, работает:

Код: sql
1.
2.
3.
4.
5.
6.
7.
DELIMITER // 
DROP TRIGGER IF EXISTS `gen_grp_id` // 
CREATE TRIGGER `gen_grp_id` AFTER INSERT ON `b` FOR EACH ROW 
BEGIN 
SET @inc = (SELECT SetAutoInc(CONCAT('B#',NEW._to,'#',NEW._year)); 
END// 
DELIMITER ; 



что не так с
Код: sql
1.
NEW.id_grp = @inc; 


понять не могу...

mysql> select * from b_inc;
Empty set (0.00 sec)

mysql> insert into b (_to,_year,name) values (1,2018,'123')
-> ;
Query OK, 1 row affected (0.03 sec)

mysql> insert into b (_to,_year,name) values (1,2018,'123');
Query OK, 1 row affected (0.04 sec)

mysql> select * from b_inc;
+----+----------+-----+
| id | id_tbl | inc |
+----+----------+-----+
| 7 | B#1#2018 | 2 |
+----+----------+-----+
1 row in set (0.00 sec)

tip78что за дичь, почему вот так то нельзя?
Код: sql
1.
INSERT INTO tbl (grp,name,cnt) VALUES (1,2,(SELECT (max(cnt) +1) AS cnt FROM tbl WHERE grp = 'fish'))


Хм..., сказать честно, может и можно ))) Не ищу я легких путей... ))) За совет большое спасибо!
А не может ли получиться так, что при вставлении записи будет удалена последняя запись и вставляемая получит его ID?
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39637685
tip78
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
systistratorХм..., сказать честно, может и можно ))) Не ищу я легких путей... ))) За совет большое спасибо!
А не может ли получиться так, что при вставлении записи будет удалена последняя запись и вставляемая получит его ID?
ну у вас там написано AFTER INSERT, я от этого и пляшу
давайте спляшем от другого тогда - а зачем вам эти дыры в записях?? Вы даже не будете знать "а что там было".
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39637788
systistrator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
tip78Вы даже не будете знать "а что там было".
Нет, знать, что там было я знать все равно буду, т.к. будет ещё журналирование событий.
Но в целом думаю ваш вариант для меня вполне подходит, просто буду не удалять записи а введу поле _del и буду помечать при необходимости. Большое вам спасибо!

Но что не так с триггером мне все равно интересно, для опыта пригодится )))
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39637796
tip78
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
systistratorНет, знать, что там было я знать все равно буду, т.к. будет ещё журналирование событий.
ну так тем более они вообще нафиг не нужны
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39637798
systistrator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
tip78systistratorНет, знать, что там было я знать все равно буду, т.к. будет ещё журналирование событий.
ну так тем более они вообще нафиг не нужны

Дело в том, что недопустимо если будет существовать два документа с одним номером... Засудят...

Я так понял, нельзя при insert делать select к этой же таблице

INSERT INTO b (`id_to`,`_year`,`name`,`id_grp`) VALUES (33,2017,"1",(SELECT (max(id_grp) + 1) AS cnt FROM b WHERE id_to = 33 AND _year = 2017))

Ответ MySQL:
#1093 - Не допускается указание таблицы 'b' в списке таблиц FROM для внесения в нее изменений
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39637807
tip78
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
systistratortip78пропущено...

ну так тем более они вообще нафиг не нужны

Дело в том, что недопустимо если будет существовать два документа с одним номером... Засудят...
так у вас ID есть с автоинкрементом, он всегда поставит следующий №
если удалите 32, то следующий всё-равно будет 33, последовательность помнит.

Я так понял, нельзя при insert делать select к этой же таблице

INSERT INTO b (`id_to`,`_year`,`name`,`id_grp`) VALUES (33,2017,"1",(SELECT (max(id_grp) + 1) AS cnt FROM b WHERE id_to = 33 AND _year = 2017))

Ответ MySQL:
#1093 - Не допускается указание таблицы 'b' в списке таблиц FROM для внесения в нее изменений
lol
в пг можно
ну сделайте отдельно селект ДО insert
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39637844
tip78
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
но вообще вам это в новой парадигме не нужно совершенно
при селекте выведете эти цифры
...
Рейтинг: 0 / 0
Вопрос по инкременту в MyISAM
    #39638108
systistrator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В целом я наконец-то нашел недочет в триггере... ))

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
DELIMITER // 
DROP TRIGGER IF EXISTS `gen_grp_id` // 
CREATE TRIGGER `gen_grp_id` BEFORE INSERT ON `b` FOR EACH ROW 
BEGIN 
DECLARE inc INT;
SELECT setAutoInc(CONCAT('B#',NEW._to,'#',NEW._year)) INTO inc;
SET NEW.id_grp = inc; 
END// 
DELIMITER ; 



Код: sql
1.
insert into b (_to,_year,name) values (1,2017,'1');


Query OK, 1 row affected (0.02 sec)

Код: sql
1.
insert into b (_to,_year,name) values (1,2017,'2');


Query OK, 1 row affected (0.03 sec)

Код: sql
1.
insert into b (_to,_year,name) values (1,2017,'3');


Query OK, 1 row affected (0.01 sec)

Код: sql
1.
insert into b (_to,_year,name) values (1,2018,'4');


Query OK, 1 row affected (0.02 sec)

Код: sql
1.
insert into b (_to,_year,name) values (1,2018,'5');


Query OK, 1 row affected (0.03 sec)

Код: sql
1.
insert into b (_to,_year,name) values (2,2017,'6');


Query OK, 1 row affected (0.03 sec)

Код: sql
1.
select * from b;


+----+--------+-----+-------+------+
| id | id_grp | _to | _year | name |
+----+--------+-----+-------+------+
| 51 | 1 | 1 | 2017 | 1 |
| 52 | 2 | 1 | 2017 | 2 |
| 53 | 3 | 1 | 2017 | 3 |
| 54 | 1 | 1 | 2018 | 4 |
| 55 | 2 | 1 | 2018 | 5 |
| 56 | 1 | 2 | 2017 | 6 |
+----+--------+-----+-------+------+
6 rows in set (0.00 sec)

Код: sql
1.
select * from b_inc;


+----+----------+-----+
| id | id_tbl | inc |
+----+----------+-----+
| 23 | B#1#2017 | 3 |
| 24 | B#1#2018 | 2 |
| 25 | B#2#2017 | 1 |
+----+----------+-----+
3 rows in set (0.00 sec)
...
Рейтинг: 0 / 0
23 сообщений из 23, страница 1 из 1
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Вопрос по инкременту в MyISAM
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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