sql >> Database teknologi >  >> RDS >> Mysql

MySQL-OPDATERING:Top 5 tips til T-SQL-udviklere

Tilføjer du MySQL til din liste over databasefærdighedssæt? Så er MySQL UPDATE-sætning en af ​​de kommandoer, du skal lære.

Vi fortsætter vores rejse til MySQL fra SQL Server synspunkt. Det startede med CREATE TABLE, efterfulgt af INSERT, og det seneste stykke handlede om DELETE. I dag er UPDATE vores omdrejningspunkt.

Forskellene er subtile og nemme at lære. Men ligesom i de tidligere artikler, er vores mål at have dig hurtigt i gang. Men før vi fortsætter, lad os gøre disse punkter klare:

  • Eksemplerne, der bruges her, blev kørt på MySQL 8.0.23 ved hjælp af InnoDB-lagringsmotoren.
  • Vi brugte SQL Server 2019.

Forbered prøvedataene

Vi kan ikke fortsætte uden prøvedata. Jeg vil gerne have T-SQL-udviklere hjemme i denne øvelse. Så lad os importere nogle velkendte tabeller til AdventureWorks eksempeldatabase fra SQL Server:

  • Produkt
  • SalesOrderHeader
  • SalgOrderDetails

For at importere disse tabeller til MySQL brugte jeg dbForge Studio til MySQL. Her er trinene:

  1. Opret en ny database kaldet adventureworks2019 .
  2. Højreklik på adventureworks2019 og vælg Værktøjer .
  3. Vælg Importér data . Et nyt vindue vises.
  4. Vælg ODBC . Du skal oprette et bruger-DSN for at oprette forbindelse til din SQL Server og AdventureWorks database.
  5. Klik på Næste .
  6. Vælg den tabel, du skal importere, MySQL-forbindelsen og måldatabasen (adventureworks2019 ).
  7. Klik på Næste .
  8. Rediger kolonneindstillingerne. Du kan også se eksempeldata. Du kan springe dette over ved at klikke på Næste eller ændre indstillingerne, som det passer dig.
  9. Klik på Importer .
  10. Importer den næste tabel ved at følge de samme instruktioner på skærmen.
  11. Klik på Udfør .

Efter at have importeret disse tabeller, er du nu klar til eksemplerne i denne artikel. Så lad os begynde.

1. Grundlæggende syntaks

MySQL UPDATE-sætningssyntaksen ser sådan ud:

OPDATERING [LOW_PRIORITY] [IGNORE] table_references SET assignment_list [WHERE where_condition] [ORDER BY ...] [LIMIT row_count] 

Jeg kan næsten høre dig efter at have læst syntaksen:LAV PRIORITET, IGNORER, BESTIL EFTER, og LIMIT passer ikke! Lad os begynde at diskutere fra toppen.

For det første er LOW_PRIORITY et fremmed nøgleord for os, fordi SQL Server ikke understøtter det. Det er valgfrit, men hvis du inkluderer det, bliver opdateringer forsinket, indtil alle andre klienter ikke læser tabellen.

Et andet fremmed nøgleord er IGNORER. Det er også valgfrit, men hvis du inkluderer det, og der opstår dubletter, vil der ikke blive rejst en fejl. For flere ignorable fejl, tjek dette link.

Så BESTIL EFTER. Vi ved, hvad det er til. Men prøv det i SQL Server Management Studio, og snoede linjer vises under nøgleord.

Endelig, LIMIT. Dette er det samme som TOP i SQL Server. Mere af dette og BESTIL AF i et senere afsnit.

Det er de åbenlyse forskelle. Læs videre i de næste 2 underafsnit.

MySQL-OPDATERING Enkelt kolonne

Opdatering af en enkelt kolonne er næsten ens. Så eksemplet nedenfor vil producere det samme resultat fra begge databaseplatforme. Bemærk dog, at i stedet for backticks bruger SQL Server firkantede parenteser.

-- MySQL OPDATERING enkelt kolonne OPDATERING `production.product`SET ReorderPoint =650WHERE ProductID =316; 

Her er en tilsvarende T-SQL-syntaks:

-- T-SQL OPDATERING enkelt kolonne OPDATERING [Produktion].[Product]SET ReorderPoint =650WHERE ProductID =316; 

Værdien, der er tildelt en kolonne, kan være ethvert enkeltværdiudtryk, så længe den returnerede type er den samme som kolonnens datatype.

MySQL-OPDATERING Flere kolonner

Opdatering af flere kolonner ligner også næsten T-SQL. Her er et eksempel:

OPDATERING `production.product`SET ReorderPoint =650, SafetyStockLevel =1200WHERE ProductID =316; 

For at opdatere flere kolonner skal du blot adskille kolonne-værdi-par med et komma. Igen, den eneste forskel her er backticks.

Indtil videre er disse alle enkelt tabelopdateringer. Lad os gå videre til MySQL UPDATE fra en anden tabel.

2. MySQL-OPDATERING med JOIN

Der er mindre forskelle, du vil se, når du opdaterer en tabel med joinforbindelser. Den bedste måde at vise dette på er gennem et eksempel på brug af 3 tabeller.

OPDATERING `sales.salesorderdetail` sodINNER JOIN `sales.salesorderheader` soh ON sod.SalesOrderID =soh.SalesOrderIDINNER JOIN `production.product` p ON sod.ProductID =p.ProductIDset UnitPrice =P.Listprice. ProductID =758AND soh.OrderDate ='2012-04-30'; 

Bemærk, at nogle klausuler er arrangeret anderledes sammenlignet med SQL Server. Joins vises først før SET-klausulen. Der er heller ingen FROM-klausul. Som du kan forvente, vil SQL Server Management Studio sætte snoede linjer for den stødende syntaks. Se dette og den korrekte T-SQL-syntaks i figur 1 nedenfor.

Før opdateringen er enhedsprisværdien 874,7940 som vist i figur 2.

Efter opdateringen, Enhedspris er opdateret fra Produktet tabellens listepris . Se figur 3.

Bortset fra INNER JOIN, kan du bruge LEFT eller RIGHT JOIN afhængigt af dine krav.

3. MySQL-OPDATERING med underforespørgsel

Du kan bruge MySQL UPDATE-sætningen fra en anden tabel ved hjælp af en underforespørgsel. Forespørgslen med en joinforbindelse i det foregående afsnit kan omskrives ved hjælp af en underforespørgsel. Resultaterne vil være de samme. Her kommer:

OPDATERING `sales.salesorderdetail` sodINNER JOIN `sales.salesorderheader` soh ON sod.SalesOrderID =soh.SalesOrderIDSET sod.UnitPrice =(vælg ListePris fra `production.product` WHERE ProductID =758)WHERE sod.Product =758AND soh.OrderDate ='2012-04-30'; 

Fremgangsmåden er anderledes, men resultatet er det samme som i figur 3. Bemærk dog, at den underforespørgsel, der bruges til at opdatere en kolonne, skal returnere 1 værdi.

Der er en anden måde at udtrykke denne MySQL UPDATE-erklæring på.

4. MySQL-OPDATERING med CTE

Common Table Expressions (CTE) understøttes i både MySQL og SQL Server. Hvis du ikke er bekendt med CTE'er, så tjek den forrige artikel.

Her er den tilsvarende erklæring med CTE brugt.

WITH priceIncrease AS( SELECT soh.SalesOrderID, p.ProductID, p.ListPrice FROM `sales.salesorderdetail` sod INNER JOIN `sales.salesorderheader` soh ON sod.SalesOrderID =soh.SalesOrderID `INNER JOINproduction. product` p ON sod.ProductID =p.ProductID WHERE p.ProductID =758 AND soh.OrderDate ='2012-04-30')OPDATERING `sales.salesorderdetail` sinNER JOIN-prisForøg pi PÅ s.SalesOrderID =pi.SalesOrderID .ProductID =pi.ProductIDSET s.UnitPrice =pi.ListPrice 

SQL Server understøtter det samme koncept, men uden backticks. Resultatet bliver det samme som i figur 3.

Du kan spørge, hvilken af ​​de 3 tilgange er bedre? Vi vil sammenligne deres præstationer yderligere.

5. MySQL-OPDATERING med LIMIT

MySQL UPDATE kan begrænse antallet af rækker, der skal opdateres med nøgleordet LIMIT. Antag, at vi ønsker at opdatere 5 poster i Produktet bord. Vi kan udtrykke udsagnet sådan her:

OPDATERING `production.product` pSET p.StandardCost =p.StandardCost + 10, p.ListPrice =p.ListPrice + 10ORDER BY p.ProductIDLIMIT 5; 

Dette vil sortere posterne baseret på ProduktID , og opdater derefter de første 5 poster. Det stopper efter den 5. rekord.

SQL Serverens modstykke til LIMIT er TOP. Du kan dog ikke bare ændre nøgleordet LIMIT til TOP og forvente, at det vil fungere i SQL Server. Her er den modificerede version i T-SQL, som vil give det samme resultat:

OPDATERING Production.ProductSET StandardCost +=10, ListePris +=10WHERE ProductID IN (VÆLG TOP 5 ProductID FRA Production.Product ORDER BY ProductID) 

Logikken er lidt anderledes. Den opdaterer StandardCost og Listepris kolonner baseret på de produkt-id'er, der findes i underforespørgslen. Underforespørgslen returnerer på den anden side de første 5 poster i Produktet tabel sorteret efter ProduktID .

Selvom TOP også understøttes i T-SQL UPDATE, er ORDER BY det ikke. Brug af TOP med UPDATE vil således ændre tilfældige poster. Ovenstående syntaks gælder for bestilte poster med TOP.

MySQL OPDATERING Ydeevne

Tidligere havde vi en UPDATE-erklæring med de samme resultater, selvom vi brugte forskellige metoder. Vi brugte JOIN, underforespørgsel og CTE. Hvilken af ​​dem klarer sig bedst?

Der er også en eksekveringsplan i MySQL, der bruger søgeordet EXPLAIN. Syntaksen er sådan her:

EXPLAIN [FORMAT=JSON] 

Uden JSON-formatet har du grundlæggende oplysninger som tabeller, brugte indeksnøgler og scannede rækker. Når JSON-formatet er angivet, har du mere detaljerede oplysninger. dbForge Studio til MySQL inkluderer en Query Profiler ud over resultatet af EXPLAIN. MySQL Workbench indeholder en Visual EXPLAIN, hvor du kan se en grafisk visning af planen baseret på EXPLAIN FORMAT=JSON.

Nu hvor vi kender kommandolinjeudsagn og grafiske værktøjer, hvordan kan vi så bruge dem til at sammenligne forskellige metoder?

Inden vi fortsætter, lad mig være ærlig. Mine færdigheder i SQL Server er højere end i MySQL. Jeg kan gå glip af noget undervejs eller tage fejl. Du kan udfylde hullerne i kommentarfeltet senere.

Dissekere EXPLAIN-resultater for UPDATE med JOIN

Første gang jeg kørte MySQL UPDATE-sætningen med JOIN, tog det 11,3 sekunder for 24 rækker opdaterede. Utroligt, ikke?

Her er, hvad der skete som set i dbForge Studio. Se figur 4 nedenfor.

Hvad fortæller figur 4 os?

  1. De 3 anvendte tabelaliasser er der. Alle 3 har adgangstyper af ALLE. Det betyder, at MySQL brugte Table Scan for alle 3.
  2. Se på tasten kolonne. Der vises intet på alle 3 tabeller, hvilket betyder, at der ikke blev brugt indeksnøgler. Dette understøtter det forrige punkt i Tabelscanning.
  3. Til sidst, rækkerne kolonne. Den fortæller, hvor mange rækker MySQL mener, den skal scanne for at opnå det endelige resultat. For 24 opdaterede rækker blev tusindvis af rækker scannet for SalesOrderHeader og SalesOrderDetails . I mellemtiden er alle rækker i Produktet tabellen blev scannet.

Jeg kløede mig i hovedet, da jeg lærte dette. Jeg indså, at når jeg importerede tabeller fra SQL Server, blev kun tabelstrukturen og dataene importeret, ikke indekserne .

Så jeg oprettede passende indekser og primære nøgler i dbForge Studio. Her er, hvad jeg har lavet:

  • Jeg har lavet Produkt-id'et i Produkt tabel en primær nøgle.
  • Jeg tilføjede også SalesOrderID som en primær nøgle i SalesOrderHeader bord. Derefter lavede jeg et indeks for OrderDate også.
  • Til sidst lavede jeg SalesOrderDetailID i SalesOrderDetail tabel en primær nøgle. Jeg tilføjede også et indeks for SalesOrderID og ProduktID kolonner i denne tabel.

Herefter genererede jeg en ny eksekveringsplan for den samme forespørgsel for at se forbedringerne. Resultatet?

HASTIGHED EFTER TILFØJELSE AF INDEKSER

Udførelsestiden blev reduceret fra 11,3 sekunder til 0,019 sekunder. Meget fedt!

Lad os tjekke den nye plan ved hjælp af dbForge Studio i figur 5 nedenfor.

Hvad fortæller figur 5 os?

  • adgangen typer af 3 borde blev ændret. De 2 værdier, der skal undgås her, er ALL og INDEX, især på store borde. ALL er Table Scan og INDEX er Index Scan.
  • Nøglen kolonne inkluderer nu de anvendte indekser. Det er godt. Alle tilføjede indekser blev brugt.
  • rækkerne kolonne viser nu mindre tal. De tilføjede indekser reducerede en masse I/O på vores forespørgsel.

For mere information om EXPLAIN detaljerne og værdierne, se denne officielle dokumentation.

Men hvordan er dette sammenlignet med MySQL UPDATE med underforespørgsel?

Dissekere EXPLAIN-resultater for UPDATE med underforespørgsel

Den tidligere forespørgsel om at opdatere Enhedsprisen kolonne har et andet forespørgselsalternativ, som bruger en underforespørgsel. Hvordan er det sammenlignet med JOIN? Se figur 6 nedenfor.

Figur 6 viser:

  • Type-, nøgle- og rækkekolonneværdier er de samme sammenlignet med at bruge JOIN. Dette er logisk, da det burde have de samme resultater.
  • Udførelsestiden tog lidt hurtigere. Dette vil dog ikke ske hver gang. Det afhænger af de nuværende ressourcer til rådighed. Hastighedsforskellen er også ubetydelig. Du vil slet ikke mærke det.

En anden måde er at bruge EXPLAIN FORMAT=JSON for at få flere oplysninger om planen. Ved kontrol er forespørgselsomkostningerne (84,79) og prisoplysninger de samme.

Lad os nu sammenligne det med MySQL UPDATE med CTE.

Dissekere EXPLAIN-resultater for UPDATE med CTE

Brug af CTE som grundlag for opdatering af Enhedsprisen kolonne er som at have en midlertidig tabel først og derefter forbinde den midlertidige tabel til SalesOrderDetails . Ved første øjekast kan det se ud til, at det ikke er en god mulighed sammenlignet med de to første. Men det viser os, at det er muligt at få en opdatering i MySQL ved hjælp af CTE. Det kan være en god mulighed i andre situationer. I hvert fald, lad os få FORKLAR resultaterne for denne tilgang.

Hvis du ikke har dbForge Studio til MySQL, kan du prøve at producere EXPLAIN-resultater ved at bruge kommandoen i en hvilken som helst anden editor. Her er et eksempel:

EXPLAINWITH priceIncrease AS( SELECT soh.SalesOrderID, p.ProductID, p.ListPrice FROM `sales.salesorderdetail` sod INNER JOIN `sales.salesorderheader` soh ON sod.SalesOrderID =soh.SalesOrderID INNER JOIN. product` p ON sod.ProductID =p.ProductID WHERE p.ProductID =758 AND soh.OrderDate ='2012-04-30')OPDATERING `sales.salesorderdetail` sinNER JOIN-prisForøg pi PÅ s.SalesOrderID =pi.SalesOrderID .ProductID =pi.ProductIDSET s.UnitPrice =pi.ListPrice

Resultatet er i figur 7 nedenfor.

Figur 7 viser:

  • 4 tabeller blev brugt i stedet for 3. Den første brug af SalesOrderDetail er i CTE og derefter i UPDATE-sætningen.
  • Flere tabeller betyder flere rækker sammenlignet med de 2 tidligere tilgange.

Overraskende nok kørte denne på 0,015 sekunder (ikke vist på figuren). Det samme er med at bruge en underforespørgsel. Det vil dog ikke ske hver gang. Det afhænger af de tilgængelige systemressourcer på tidspunktet for udførelse.

Den samlede forespørgselsomkostning er 166,69. Det er højere end de tidligere 2 tilgange. Jo lavere forespørgselsomkostninger er, desto bedre ydeevne over tid.

Takeaways

Vi tog et dybt dyk ned i forskellene mellem MySQL og SQL Servers UPDATE-sætning. Vi har lært, hvordan det gøres ved opdatering

  • en enkelt kolonne
  • flere kolonner
  • tabeller med et join
  • kolonner ved hjælp af en underforespørgsel
  • tabeller med en CTE
  • med en LIMIT

I dette indlæg fik du også et smugkig om EXPLAIN, og hvordan du bruger det til at sammenligne forskellige UPDATE-tilgange.

Jeg håber, at dette kan være nyttigt for dig, når du lærer MySQL fra SQL Server. Hvis du kan lide dette opslag, bedes du dele det på dine foretrukne sociale medieplatforme. Og hvis der mangler noget, så lad os det vide i kommentarfeltet.

God kodning!


  1. MySQL FEJL 1290 (HY000) --secure-file-priv mulighed

  2. Grunde til at forvandle Access Apps til webbaserede apps

  3. SQL Server VIS TABELLER Tilsvarende

  4. Authentication plugin 'caching_sha2_password' kan ikke indlæses