sql >> Database >  >> RDS >> Mysql

MySQL UPDATE:Top 5 tips voor T-SQL-ontwikkelaars

Voegt u MySQL toe aan uw lijst met databasevaardigheden? Dan is de MySQL UPDATE-instructie een van de opdrachten die u moet leren.

We vervolgen onze reis naar MySQL vanuit het oogpunt van SQL Server. Het begon met CREATE TABLE, gevolgd door INSERT, en het meest recente stuk ging over DELETE. Vandaag staat UPDATE centraal.

De verschillen zijn subtiel en gemakkelijk te leren. Maar net als in de vorige artikelen is ons doel om u snel aan de slag te hebben. Maar voordat we verder gaan, laten we deze punten duidelijk maken:

  • De hier gebruikte voorbeelden zijn uitgevoerd op MySQL 8.0.23 met behulp van de InnoDB-opslagengine.
  • We gebruikten SQL Server 2019.

Bereid de voorbeeldgegevens voor

We kunnen niet verder zonder voorbeeldgegevens. Bij deze oefening zou ik T-SQL-ontwikkelaars thuis willen betrekken. Laten we dus enkele bekende tabellen importeren in de AdventureWorks voorbeelddatabase van SQL Server:

  • Product
  • SalesOrderHeader
  • SalesOrderDetails

Om deze tabellen in MySQL te importeren, heb ik dbForge Studio voor MySQL gebruikt. Dit zijn de stappen:

  1. Maak een nieuwe database met de naam adventureworks2019 .
  2. Klik met de rechtermuisknop op adventureworks2019 en selecteer Extra .
  3. Selecteer Gegevens importeren . Er verschijnt een nieuw venster.
  4. Selecteer ODBC . U moet een Gebruikers-DSN . maken om verbinding te maken met uw SQL Server en de AdventureWorks database.
  5. Klik op Volgende .
  6. Selecteer de tabel die u wilt importeren, de MySQL-verbinding en de doeldatabase (adventureworks2019 ).
  7. Klik op Volgende .
  8. Wijzig de kolominstellingen. U kunt ook voorbeeldgegevens bekijken. U kunt dit overslaan door te klikken op Volgende of verander de instellingen naar eigen inzicht.
  9. Klik op Importeren .
  10. Importeer de volgende tabel door dezelfde instructies op het scherm te volgen.
  11. Klik op Voltooien .

Na het importeren van deze tabellen ben je klaar voor de voorbeelden in dit artikel. Laten we beginnen.

1. Basissyntaxis

De syntaxis van de MySQL UPDATE-instructie gaat als volgt:

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

Ik kan je bijna horen na het lezen van de syntaxis:LOW PRIORITY, IGNORE, ORDER BY en LIMIT passen niet! Laten we beginnen met bespreken vanaf de top.

Ten eerste is LOW_PRIORITY een vreemd sleutelwoord voor ons omdat SQL Server dit niet ondersteunt. Het is optioneel, maar als je het opneemt, worden updates uitgesteld totdat alle andere clients de tabel niet lezen.

Een ander buitenaards sleutelwoord is NEGEREN. Het is ook optioneel, maar als u het opneemt en er duplicaten optreden, wordt er geen fout gegenereerd. Bekijk deze link voor meer onmiskenbare fouten.

BESTEL dan DOOR. We weten waarvoor het dient. Maar probeer het in SQL Server Management Studio en er verschijnen kronkelige lijnen onder trefwoorden.

Eindelijk, LIMIET. Dit is hetzelfde als TOP in SQL Server. Meer hierover en BESTEL DOOR in een later gedeelte.

Dit zijn de voor de hand liggende verschillen. Lees verder in de volgende 2 subparagrafen.

MySQL UPDATE enkele kolom

Het bijwerken van een enkele kolom is bijna hetzelfde. Het onderstaande voorbeeld zal dus hetzelfde resultaat opleveren van beide databaseplatforms. Houd er echter rekening mee dat SQL Server vierkante haken gebruikt in plaats van backticks.

-- MySQL UPDATE single column
UPDATE `production.product`
SET ReorderPoint = 650
WHERE ProductID = 316;

Hier is een equivalente T-SQL-syntaxis:

-- T-SQL UPDATE single column
UPDATE [Production].[Product]
SET ReorderPoint = 650
WHERE ProductID = 316;

De waarde die aan een kolom wordt toegewezen, kan elke expressie met één waarde zijn, zolang het geretourneerde type hetzelfde is als het gegevenstype van de kolom.

MySQL UPDATE Meerdere kolommen

Het bijwerken van meerdere kolommen is ook bijna hetzelfde als T-SQL. Hier is een voorbeeld:

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

Om meerdere kolommen bij te werken, scheidt u kolomwaardeparen eenvoudig met een komma. Nogmaals, het enige verschil hier zijn de backticks.

Tot nu toe zijn dit allemaal updates voor één tafel. Laten we verder gaan met MySQL UPDATE vanaf een andere tafel.

2. MySQL-UPDATE met JOIN

Er zijn kleine verschillen die u zult zien bij het bijwerken van een tabel met joins. De beste manier om dit te laten zien is door middel van een voorbeeld van het gebruik van 3 tabellen.

UPDATE `sales.salesorderdetail` sod
INNER JOIN `sales.salesorderheader` soh ON sod.SalesOrderID = soh.SalesOrderID
INNER JOIN `production.product` p ON sod.ProductID = p.ProductID
set UnitPrice = p.ListPrice
WHERE p.ProductID = 758
AND soh.OrderDate = '2012-04-30';

Merk op dat sommige clausules anders zijn gerangschikt in vergelijking met SQL Server. Joins verschijnen eerst vóór de SET-component. Er is ook geen FROM-clausule. Zoals je kunt verwachten, zal SQL Server Management Studio kronkelige lijnen plaatsen voor de aanstootgevende syntaxis. Zie dit en de juiste T-SQL-syntaxis in Afbeelding 1 hieronder.

Vóór de update was de waarde van de eenheidsprijs 874,7940, zoals te zien is in figuur 2.

Na de update, Eenheidsprijs is bijgewerkt vanaf het Product tabel's LijstPrijs . Zie figuur 3.

Afgezien van INNER JOIN, kunt u LEFT of RIGHT JOIN gebruiken, afhankelijk van uw vereisten.

3. MySQL-UPDATE met subquery

U kunt de MySQL UPDATE-instructie uit een andere tabel gebruiken met behulp van een subquery. De query met een join in de vorige sectie kan worden herschreven met behulp van een subquery. De resultaten zullen hetzelfde zijn. Hier gaat het:

UPDATE `sales.salesorderdetail` sod
INNER JOIN `sales.salesorderheader` soh ON sod.SalesOrderID = soh.SalesOrderID
SET sod.UnitPrice = (select ListPrice from `production.product` WHERE ProductID = 758)
WHERE sod.ProductID = 758
AND soh.OrderDate = '2012-04-30';

De aanpak is anders, maar het resultaat is hetzelfde als in Afbeelding 3. Houd er echter rekening mee dat de subquery die wordt gebruikt om een ​​kolom bij te werken, 1 waarde moet retourneren.

Er is een andere manier om deze MySQL UPDATE-instructie uit te drukken.

4. MySQL-UPDATE met CTE

Common Table Expressions (CTE) worden ondersteund in zowel MySQL als SQL Server. Als je niet bekend bent met CTE's, bekijk dan het vorige artikel.

Nu, hier is de equivalente verklaring met CTE gebruikt.

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 JOIN `production.product` p ON sod.ProductID = p.ProductID
  WHERE p.ProductID = 758
  AND soh.OrderDate = '2012-04-30'
)
UPDATE `sales.salesorderdetail` s
INNER JOIN priceIncrease pi ON s.SalesOrderID = pi.SalesOrderID AND s.ProductID = pi.ProductID
SET s.UnitPrice = pi.ListPrice

SQL Server ondersteunt hetzelfde concept, maar zonder backticks. Het resultaat is hetzelfde als in figuur 3.

U kunt zich afvragen, welke van de 3 benaderingen is beter? We zullen hun prestaties verder vergelijken.

5. MySQL-UPDATE met LIMIT

MySQL UPDATE kan het aantal te updaten rijen beperken met het trefwoord LIMIT. Stel dat we 5 records willen bijwerken in het Product tafel. We kunnen de verklaring als volgt uitdrukken:

UPDATE `production.product` p
SET p.StandardCost = p.StandardCost + 10, p.ListPrice = p.ListPrice + 10
ORDER BY p.ProductID
LIMIT 5;

Dit sorteert de records op basis van ProductID en werk vervolgens de eerste 5 records bij. Het stopt na het 5e record.

De tegenhanger van de SQL Server van LIMIT is TOP. U kunt echter niet zomaar het trefwoord LIMIT in TOP wijzigen en verwachten dat het in SQL Server zal werken. Hier is de aangepaste versie in T-SQL die hetzelfde resultaat zal geven:

UPDATE Production.Product
SET StandardCost += 10, ListPrice += 10
WHERE ProductID IN (SELECT TOP 5 ProductID 
		    FROM Production.Product 
		    ORDER BY ProductID)

De logica is een beetje anders. Het werkt Standaardkosten bij en Lijstprijs kolommen op basis van de Product-ID's die in de subquery zijn gevonden. De subquery daarentegen retourneert de eerste 5 records van het Product tabel gesorteerd op ProductID .

Hoewel TOP ook wordt ondersteund in T-SQL UPDATE, is ORDER BY dat niet. Dus het gebruik van TOP met UPDATE zal willekeurige records wijzigen. De bovenstaande syntaxis is van toepassing op bestelde records met TOP.

MySQL UPDATE-prestaties

Eerder hadden we een UPDATE-statement met dezelfde resultaten, hoewel we verschillende methoden gebruikten. We gebruikten een JOIN, subquery en CTE. Welke van hen zal het beste presteren?

Er is ook een uitvoeringsplan in MySQL met behulp van het EXPLAIN-sleutelwoord. De syntaxis is als volgt:

EXPLAIN [FORMAT=JSON]
<SQL statement>

Zonder het JSON-formaat hebt u basisinformatie zoals tabellen, gebruikte indexsleutels en gescande rijen. Wanneer de JSON-indeling is opgegeven, beschikt u over meer gedetailleerde informatie. dbForge Studio voor MySQL bevat een Query Profiler naast het resultaat van EXPLAIN. MySQL Workbench bevat een Visual EXPLAIN waar u een grafische weergave van het plan kunt zien op basis van EXPLAIN FORMAT=JSON.

Nu we de opdrachtregelinstructies en grafische hulpmiddelen kennen, hoe kunnen we ze dan gebruiken om verschillende methoden te vergelijken?

Voordat we verder gaan, laat me eerlijk zijn. Mijn vaardigheid in SQL Server is hoger dan in MySQL. Misschien mis ik onderweg iets of heb ik het mis. Je kunt de gaten in het gedeelte Opmerkingen later opvullen.

Ontleden EXPLAIN-resultaten voor UPDATE met JOIN

De eerste keer dat ik de MySQL UPDATE-instructie met JOIN uitvoerde, duurde het 11,3 seconden voordat 24 rijen waren bijgewerkt. Ongelooflijk, nietwaar?

Dit is wat er gebeurde zoals te zien is in dbForge Studio. Bekijk figuur 4 hieronder.

Wat vertelt figuur 4 ons?

  1. De 3 gebruikte tabelaliassen zijn aanwezig. Alle 3 hebben toegang tot ALL. Het betekent dat MySQL Table Scan voor alle 3 heeft gebruikt.
  2. Kijk naar de sleutel kolom. Er wordt niets weergegeven op alle 3 de tabellen, wat betekent dat er geen indexsleutels zijn gebruikt. Dit ondersteunt het vorige punt van Table Scan.
  3. Eindelijk, de rijen kolom. Het vertelt hoeveel rijen MySQL denkt te moeten scannen om het uiteindelijke resultaat te bereiken. Voor 24 bijgewerkte rijen werden duizenden rijen gescand voor SalesOrderHeader en SalesOrderDetails . Ondertussen zijn alle rijen van het Product tafel zijn gescand.

Ik krabde mijn hoofd toen ik dit hoorde. Ik realiseerde me dat toen ik tabellen uit SQL Server importeerde, alleen de tabelstructuur en de gegevens werden geïmporteerd, niet de indexen .

Dus heb ik geschikte indexen en primaire sleutels gemaakt in dbForge Studio. Dit is wat ik heb gemaakt:

  • Ik heb de ProductID . gemaakt in het Product tabel een primaire sleutel.
  • Ik heb ook SalesOrderID toegevoegd als primaire sleutel in de SalesOrderHeader tafel. Vervolgens heb ik een index gemaakt voor OrderDate ook.
  • Eindelijk heb ik SalesOrderDetailID made gemaakt in de SalesOrderDetail tabel een primaire sleutel. Ik heb ook een index toegevoegd voor de SalesOrderID en ProductID kolommen van deze tabel.

Hierna heb ik een nieuw uitvoeringsplan voor dezelfde query gegenereerd om de verbeteringen te zien. Het resultaat?

SPEED BOOST NA TOEVOEGEN VAN INDEXES

De uitvoeringstijd werd teruggebracht van 11,3 seconden naar 0,019 seconden. Heel gaaf!

Laten we het nieuwe plan eens bekijken met dbForge Studio in Afbeelding 5 hieronder.

Wat vertelt figuur 5 ons?

  • De toegang typen van 3 tabellen zijn gewijzigd. De 2 waarden die hier moeten worden vermeden, zijn ALL en INDEX, vooral bij grote tabellen. ALL is Tabel Scan en INDEX is Index Scan.
  • De sleutel kolom bevat nu de gebruikte indexen. Dit is goed. Alle toegevoegde indexen zijn gebruikt.
  • De rijen kolom toont nu kleinere cijfers. De toegevoegde indexen verminderden veel I/O op onze vraag.

Raadpleeg deze officiële documentatie voor meer informatie over de EXPLAIN details en waarden.

Maar hoe verhoudt dit zich tot MySQL UPDATE met subquery?

Ontcijferen van EXPLAIN-resultaten voor UPDATE met subquery

De vorige vraag om de Eenheidsprijs . bij te werken kolom heeft een ander query-alternatief, dat een subquery gebruikt. Hoe verhoudt het zich tot de JOIN? Bekijk figuur 6 hieronder.

Afbeelding 6 toont:

  • Type-, sleutel- en rijkolomwaarden zijn hetzelfde in vergelijking met het gebruik van JOIN. Dit is logisch omdat het dezelfde resultaten zou moeten hebben.
  • De uitvoeringstijd duurde iets sneller. Dit zal echter niet elke keer gebeuren. Het hangt af van de huidige beschikbare middelen. Ook het snelheidsverschil is verwaarloosbaar. Je voelt het helemaal niet.

Een andere manier is om EXPLAIN FORMAT=JSON te gebruiken om meer informatie over het plan te krijgen. Bij controle zijn de querykosten (84,79) en de kosteninformatiewaarden hetzelfde.

Laten we het nu eens vergelijken met MySQL UPDATE met CTE.

Ontleden EXPLAIN-resultaten voor UPDATE met CTE

CTE gebruiken als basis voor het bijwerken van de Eenheidsprijs kolom is alsof je eerst een tijdelijke tabel hebt en vervolgens de tijdelijke tabel toevoegt aan SalesOrderDetails . Op het eerste gezicht lijkt het misschien geen goede optie in vergelijking met de eerste twee. Maar het laat ons zien dat het mogelijk is om een ​​update in MySQL te hebben met CTE. In andere situaties kan het een goede optie zijn. Hoe dan ook, laten we de EXPLAIN-resultaten voor deze aanpak hebben.

Als u dbForge Studio voor MySQL niet hebt, kunt u proberen EXPLAIN-resultaten te produceren met de opdracht in een andere editor. Hier is een voorbeeld:

EXPLAIN
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 JOIN `production.product` p ON sod.ProductID = p.ProductID
  WHERE p.ProductID = 758
  AND soh.OrderDate = '2012-04-30'
)
UPDATE `sales.salesorderdetail` s
INNER JOIN priceIncrease pi ON s.SalesOrderID = pi.SalesOrderID AND s.ProductID = pi.ProductID
SET s.UnitPrice = pi.ListPrice

Het resultaat staat in Afbeelding 7 hieronder.

Afbeelding 7 toont:

  • Er werden 4 tabellen gebruikt in plaats van 3. Het eerste gebruik van SalesOrderDetail staat in de CTE en vervolgens in de UPDATE-instructie.
  • Meer tabellen betekenen meer rijen in vergelijking met de 2 eerdere benaderingen.

Verrassend genoeg liep dit op 0,015 seconden (niet weergegeven in de afbeelding). Hetzelfde geldt voor het gebruik van een subquery. Het zal echter niet elke keer gebeuren. Het hangt af van de systeembronnen die beschikbaar zijn op het moment van uitvoering.

De totale kosten voor zoekopdrachten zijn 166,69. Het is hoger dan de vorige 2 benaderingen. Hoe lager de querykosten, hoe beter voor de prestaties in de loop van de tijd.

Afhaalmaaltijden

We hebben een diepe duik genomen in de verschillen tussen MySQL en de UPDATE-instructie van SQL Server. We hebben geleerd hoe het moet bij het updaten

  • een enkele kolom
  • meerdere kolommen
  • tafels met een join
  • kolommen die een subquery gebruiken
  • tabellen met een CTE
  • met een LIMIET

In dit bericht heb je ook een voorproefje gehad van EXPLAIN en hoe je het kunt gebruiken om verschillende UPDATE-benaderingen te vergelijken.

Ik hoop dat dit je kan helpen als je leert dat MySQL afkomstig is van SQL Server. Als je dit bericht leuk vindt, deel het dan op je favoriete sociale mediaplatforms. En als er iets ontbreekt, laat het ons dan weten in het gedeelte Opmerkingen.

Veel plezier met coderen!


  1. TIMEDIFF() Voorbeelden – MySQL

  2. Logische PostgreSQL-replicatie gebruiken om een ​​altijd up-to-date lees/schrijf TEST-server te onderhouden

  3. Als u geïndexeerde weergaven en MERGE gebruikt, lees dit dan alstublieft!

  4. Hoe DbContext configureren om te werken met Oracle ODP.Net en EF CodeFirst?