sql >> Databasteknik >  >> RDS >> Mysql

mysql På Duplicera värde i fält, infoga ny rad med nytt värde

EDIT:

Redigerat efter användarkommentar till detta inlägg:

Du behöver skrivtabelllåsning på båda dessa två processer.

Ett WRITE-lås har följande funktioner:

  • Den enda session som håller låset för en tabell kan läsa och skriva data från tabellen.

  • Andra sessioner kan inte läsa data från och skriva data till tabellen förrän WRITE-låset släpps.

Titta även på SQL UNIQUE Constraint

INNAN REDIGERING:

Ja det är möjligt. Och det tog mig ett tag att komma på det. Jag bygger detta på dina indata och jämförande värden som test1, test2 etc, där testet alltid är detsamma och har efterföljande nummer. Som du angav.

Det kan göras som MySQL-TRANSACTION i 4 steg.

Låt säga att du har tabellen testT där namnet är unikt för att säkerställa att vi inte har några dubbelgångar.

| id  | name  |
| --- | ----- |
| 1   | test1 |
| 2   | test3 |

Och du vill infoga ett nytt objekt med namnet test1 vi ställer in som:

SET @newName = 'test1'; 

Sedan måste vi kontrollera om det redan finns i tabellen:

SELECT @check:=COUNT(*) FROM testT WHERE name = @newName;    

Vi räknar här för att få sant eller falskt och sparar det som @check här så att vi kan jämföra det senare. Detta kommer att resultera i 1 row som test1 finns redan i tabellen.

Därefter gör vi ett annat val för att få det högsta antalet test* och lagrar det som @number , denna nästa fråga väljer alla tester och gör en SUBSTRING efter 4 senare ger oss alla siffror efter de första 4 senare. (99999999999) siffror faktiskt bara för att vara säkra på att vi inte missar någon men i vårt fall är resultatet bara "3" eftersom det är sista posten "test3 " i tabellen.

SELECT 
    @number:= SUBSTRING(name,5,99999999999) 
FROM testT; 

Nu kan vi göra en infogning:

INSERT INTO testT(name)
VALUES
(
    IF(@check = "", @newName , CONCAT(LEFT(@newName,4),RIGHT(@number,1)+1)
)
);

Detta försöker infoga vårt @newName i tabellen under IF-villkor, och det är om vår @check är tom kommer han att infoga @newName , om inte kommer det att ta ordtestet ur strängen och lägga till en högsta @number från tidigare och lägg till +1 för det.

Så resultatet för @newName = 'test1' är under. Om du ändrar detta till @newName = 'test3' resultat skulle vara samma nya infoga test4 .

**Schema (MySQL v5.7)**

    SET @newName = 'test1';   

---

**Query #1**

    SELECT * FROM testT
     ORDER BY id;

| id  | name  |
| --- | ----- |
| 1   | test1 |
| 2   | test3 |
| 3   | test4 |

---

Och om du ändrar det i NÅGOT test* som numret inte redan finns kommer det att infoga det normalt. I fallet nedan:@newName = 'test6'

SET @newName = 'test6';
    **Query #1**

        SELECT * FROM testT
         ORDER BY id;

    | id  | name  |
    | --- | ----- |
    | 1   | test1 |
    | 2   | test3 |
    | 3   | test6 |

På så sätt kommer alltid en insats att göras.

Du kan spela med detta här :Visa på DB Fiddle bara genom att ändra SET @newName = 'test6'

Jag är ingen expert och det tog mig ett par timmar att ta reda på detta, eftersom jag ville veta om detta ens var möjligt. Och jag skulle uppskatta om någon annan användare kan föreslå något annat sätt eller förbättra min metod.




  1. Varför är en UDF så mycket långsammare än en underfråga?

  2. MySQL 5.7:konvertera enkel JSON_ARRAY till rader

  3. Fylla i luckor i datum som returneras från databasen - ren SQL-lösning möjlig?

  4. Hitta funktionellt beroende