Mysql
 sql >> Datenbank >  >> RDS >> Mysql

PHP + MYSQL auf Duplicate KEY erhöhen immer noch den INDEX KEY

ok ja, jetzt erinnere ich mich an dieses Problem. Es gab einmal einen Typen, der Einfügungen machen wollte, aber jede Einfügung musste in Schritten von 100 erfolgen wenn Sie sich vorstellen könnten, beginnend bei 1000. Und wir mussten das Ganze in eine gespeicherte Prozedur packen, um eine Schwachstelle zu haben. Ihr Problem ist aufgetaucht und hat seine Nummerierung um 1 oder so verschoben.

Indem wir es umschließen, könnten wir es vernünftigerweise mit einer Sperre tun und den auto_inc-Wert mit ALTER TABLE beibehalten

Der andere Ansatz, den ich ihm sagte, war, eine Inkrementierungstabelle zu haben, die erste Zeile zu sperren, den Wert in dieser Zeile zu erhalten, sie zu verwenden, diese IncTable um 100 zu aktualisieren. Entsperren.

Die ganze Zeit lachten wir über OCD-Probleme. Ich glaube, er mochte nur Vielfache von 10, idk

Bearbeiten:

Schema:

-- drop table ocd_nextnums;
create table ocd_nextnums
(   -- id table for nextnum, for the OCD impaired
    tableName varchar(100) not null,
    nextnum int not null
    -- won't bother with indexes, go for it if you want
)engine=INNODB; -- note engine type

insert ocd_nextnums(tableName,nextnum) values('thing',1);
insert ocd_nextnums(tableName,nextnum) values('some_other_table',1);

-- drop table thing;
create table thing
(   id int primary key, -- NOT an auto_increment, but is a PK
    email varchar(100) not null,
    version varchar(20) not null,
    lastupdate datetime not null,
    UNIQUE KEY (email)
)engine=MyIsam;

Gespeicherter Prozess:

-- drop procedure putInThing;
delimiter $$
create procedure putInThing
(
    email_In varchar(100), version_In varchar(20)
)
BEGIN
    declare toUse int;
    declare theCount int;

    select count(*) into theCount from thing where email=email_In;
    select id into toUse from thing where email=email_In;   -- useful for result set @end
    IF theCount=1 THEN
        -- was there, do UPDATE
        update thing set version=version_In,lastupdate=now() where email=email_In;
    ELSE
        -- new row, do INSERT (please note the FOR UPDATE clause)
        select nextnum into toUse from ocd_nextnums where tableName='thing' FOR UPDATE;
        update ocd_nextnums set nextnum=nextnum+1 where tableName='thing';

        insert thing(id,email,version,lastupdate) values (toUse,email_In,version_In,now());
    end if;
    select toUse;   -- <------- that was your id
END
$$

Test:

call putInThing('[email protected]','111');
call putInThing('[email protected]','121');
call putInThing('[email protected]','107');
select * from thing;
+----+----------+---------+---------------------+
| id | email    | version | lastupdate          |
+----+----------+---------+---------------------+
|  1 | [email protected] | 111     | 2015-08-14 17:08:10 |
|  2 | [email protected] | 121     | 2015-08-14 17:08:54 |
|  3 | [email protected] | 107     | 2015-08-14 17:08:56 |
+----+----------+---------+---------------------+

call putInThing('[email protected]','101111007'); -- is an update
call putInThing('[email protected]','42'); -- is an update
call putInThing('[email protected]','10007'); -- is an update
call putInThing('[email protected]','1'); -- is an insert

select * from thing;
+----+----------------------+---------+---------------------+
| id | email                | version | lastupdate          |
+----+----------------------+---------+---------------------+
|  1 | [email protected]             | 111     | 2015-08-14 17:08:10 |
|  2 | [email protected]             | 121     | 2015-08-14 17:08:54 |
|  3 | [email protected]             | 10007   | 2015-08-14 17:22:09 |
|  4 | [email protected] | 1       | 2015-08-14 17:22:47 |
+----+----------------------+---------+---------------------+

Aus dem Mysql INNODB-Teil von Manual :

Werden Sie sehen, wie ich das benutze, wahrscheinlich nicht. Einfach zeigen. Ich bin in Ordnung mit Lücken und schlafe nachts. Aus diesem Grund habe ich die erste Tabelle so benannt, wie ich sie gemacht habe:>