{"id":94959,"date":"2022-10-28T18:13:26","date_gmt":"2022-10-28T18:13:26","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=94959"},"modified":"2022-10-26T18:19:48","modified_gmt":"2022-10-26T18:19:48","slug":"introducing-the-mysql-update-statement","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/mysql\/introducing-the-mysql-update-statement\/","title":{"rendered":"Introducing the MySQL UPDATE statement"},"content":{"rendered":"<p style=\"margin: 0in; font-family: Calibri; font-size: 11.0pt;\"><p><strong>This article is part of Robert Sheldon's continuing series on Learning MySQL. To see all of the items in the series, <a href=\"https:\/\/www.red-gate.com\/simple-talk\/mysql-coding-basics\/\">click here<\/a>.<\/strong><\/p>\n<\/p>\n<p>The <code>UPDATE<\/code> statement enables you to modify values in your database tables, including temporary tables. With a single statement, you can update one or more rows, one or more columns, or any combination of the two. You can even update multiple tables. As you work through this article, you\u2019ll find that the <code>UPDATE<\/code> statement is intuitive and straightforward to use, once you understand the basics of how it works.<\/p>\n<h2>Preparing your MySQL environment<\/h2>\n<p>For the examples in this article, I used the same database (<code>travel<\/code>) and tables (<code>manufacturers<\/code> and <code>airplanes<\/code>) that I used for the last few articles in this series.<\/p>\n<p><strong>Note<\/strong>: The examples assume that you worked through the previous article, in which case, the <code>travel<\/code> database should be set up and ready to go. If you did not, you can still follow along with this article, just know that your query results will be slightly different from the ones I show here.<\/p>\n<p>To set up the <code>travel<\/code> database\u2014if you haven\u2019t already done so\u2014download the <a href=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2022\/06\/MySQL_06_setup.txt\">MySQL_06_setup.sql<\/a> file and run the SQL script against your MySQL instance. The script creates the database and tables and inserts sample data. Alternatively, you can create the database and then run the following script to create the <code>manufacturers<\/code> and <code>airplanes<\/code> tables:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">CREATE TABLE manufacturers (\r\n  manufacturer_id INT UNSIGNED NOT NULL AUTO_INCREMENT,\r\n  manufacturer VARCHAR(50) NOT NULL,\r\n  create_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\r\n  last_update TIMESTAMP NOT NULL \r\n    DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\r\n  PRIMARY KEY (manufacturer_id) ) \r\nENGINE=InnoDB AUTO_INCREMENT=1001;\r\n\r\nCREATE TABLE airplanes (\r\n  plane_id INT UNSIGNED NOT NULL AUTO_INCREMENT,\r\n  plane VARCHAR(50) NOT NULL,\r\n  manufacturer_id INT UNSIGNED NOT NULL,\r\n  engine_type VARCHAR(50) NOT NULL,\r\n  engine_count TINYINT NOT NULL,\r\n  max_weight MEDIUMINT UNSIGNED NOT NULL,\r\n  wingspan DECIMAL(5,2) NOT NULL,\r\n  plane_length DECIMAL(5,2) NOT NULL,\r\n  parking_area INT GENERATED ALWAYS \r\n             AS ((wingspan * plane_length)) STORED,\r\n  icao_code CHAR(4) NOT NULL,\r\n  create_date TIMESTAMP NOT NULL \r\n             DEFAULT CURRENT_TIMESTAMP,\r\n  last_update TIMESTAMP NOT NULL \r\n    DEFAULT CURRENT_TIMESTAMP \r\n           ON UPDATE CURRENT_TIMESTAMP,\r\n  PRIMARY KEY (plane_id),\r\n  CONSTRAINT fk_manufacturer_id \r\n    FOREIGN KEY (manufacturer_id) \r\n       REFERENCES manufacturers (manufacturer_id) ) \r\nENGINE=InnoDB AUTO_INCREMENT=101;<\/pre>\n<p>Next, you need to add data to the <code>manufacturers<\/code> and <code>airplanes<\/code> tables to support the examples in this article. Start with the <code>manufacturers<\/code> table by running the following <code>INSERT<\/code> statement, which adds Beagle Aircraft Limited as a manufacturer:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">INSERT INTO manufacturers (manufacturer)\r\nVALUES ('Beagle Aircraft Limited');\r\n\r\nSELECT manufacturer_id\r\nFROM   manufacturers\r\nWHERE  manufacturer = 'Beagle Aircraft Limited';<\/pre>\n<p>After the data is inserted, the SELECT statement returns the newly added value from the <code>manufacturer_id<\/code> column. If you\u2019ve been following along exactly with the last couple of articles, the value would be <code>1008<\/code>. If it is not, make a note of the <code>manufacturer_id<\/code> value you get here because you\u2019ll need it for the rest of the article, starting with the following <code>INSERT<\/code> statement:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">INSERT INTO airplanes \r\n  (plane, manufacturer_id, engine_type, engine_count, \r\n    wingspan, plane_length, max_weight, icao_code)\r\nVALUES \r\n  ('A.61 Terrier',1008,'piston',1,36,23.25,2400,'AUS6'),\r\n  ('B.121 Pup',1008,'piston',1,31,23.17,1600,'PUP'),\r\n  ('B.206',1008,'piston',2,55,33.67,7500,'BASS'),\r\n  ('D.4-108',1008,'piston',1,36,23.33,1900,'D4'),\r\n  ('D.5-108 Husky',1008,'piston',1,36,23.17,2400,'D5');<\/pre>\n<p>If necessary, replace <code>1008<\/code> with your <code>manufacturer_id<\/code> value and then run this statement. After you\u2019ve done that, you should be set up to follow along with the examples in this article. Be aware, however, that a number of the following examples reference the <code>manufacturer_id<\/code> column, so if the value is not <code>1008<\/code> on your system, be sure to use the correct one.<\/p>\n<h2>The <code><strong>UPDATE<\/strong><\/code> statement syntax<\/h2>\n<p>The <code>UPDATE<\/code> statement in MySQL supports five clauses, two of which are required and three that are optional, as indicated in the following syntax:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">UPDATE [IGNORE] table_name\r\nSET column = value [, column = value]...\r\n[WHERE where_condition]\r\n[ORDER BY order_list]\r\n[LIMIT row_count]<\/pre>\n<p>The syntax does not include all the elements in an <code>UPDATE<\/code> statement, but it does provide most of them. These are ones you\u2019ll be using the majority of the time, not only when learning about the statement, but also after you\u2019ve mastered it. For the complete syntax check the MySQL documentation on the <a href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/update.html\">UPDATE statement<\/a>.<\/p>\n<p>Here\u2019s a breakdown of the five clauses:<\/p>\n<ul>\n<li>The <code>UPDATE<\/code> clause, one of the statement\u2019s two mandatory clauses, specifies the table that is the target of the update. You can specify multiple tables in this clause, separating them with commas, but my focus in this article is on single-table updates. I\u2019m saving the subject of multi-table updates for when I cover more advanced topics.<\/li>\n<li>The <code>SET<\/code> clause, the other mandatory clause, specifies which columns to update. You can include one or more column assignments. For each assignment, specify the column name, an equal sign, and the new value. If you include multiple assignments, separate them with commas.<\/li>\n<li>The <code>WHERE<\/code> clause determines which rows to update, based on one or more conditions. The clause works much like the <code>WHERE<\/code> clause in a <code>SELECT<\/code> statement. Although the <code>WHERE<\/code> clause is optional, you should be very careful running an <code>UPDATE<\/code> statement that that does not include one. Without a <code>WHERE<\/code> clause, the statement will update every row in the table, unless the <code>LIMIT<\/code> clause is included.<\/li>\n<li>The <code>ORDER<\/code> <code>BY<\/code> clause specifies the order that rows should be updated. This can be useful in situations that might otherwise result in an error, as you\u2019ll see later in the article. The <code>ORDER<\/code> <code>BY<\/code> clause is similar to the one you saw in the <code>SELECT<\/code> statement. The clause cannot be used for multi-table updates.<\/li>\n<li>The <code>LIMIT<\/code> clause limits the number of rows that will be updated. If you include a <code>WHERE<\/code> clause, the count applies to the rows returned by that clause. This means that the statement will stop based on the number of rows that satisfy the <code>WHERE<\/code> conditions, whether or not those rows are actually updated. As with the <code>ORDER<\/code> <code>BY<\/code> clause, the <code>LIMIT<\/code> clause cannot be used for multi-table updates.<\/li>\n<\/ul>\n<p>With these five clauses, you can build a wide range of <code>UPDATE<\/code> statements. Most of the time, you\u2019ll be using the <code>UPDATE<\/code>, <code>SET<\/code> and <code>WHERE<\/code> clauses, although the <code>ORDER<\/code> <code>BY<\/code> clause and <code>LIMIT<\/code> clause can also come in handy at times.<\/p>\n<p>Once you see the statement in action, you should have no problem understanding how all the clauses work and using them to update data. In fact, it\u2019s almost too easy to update data, and if you\u2019re not careful, you could make a significant mess of things. Data modifications can be difficult to undo, so you need to proceed cautiously, especially when you\u2019re first learning how to use the <code>UPDATE<\/code> statement. Certainly, don\u2019t practice in a production environment. When you do update the production environment, be sure to do it within a transaction, a topic I plan to cover later in the series.<\/p>\n<h2>Performing a basic update in MySQL<\/h2>\n<p>Now that you have a basic overview of the <code>UPDATE<\/code> statement syntax, it\u2019s time to see the statement in action so you can get a feel for how it works. As I already mentioned, the <code>UPDATE<\/code> and <code>SET<\/code> clauses are the only required clauses, so let\u2019s start with them.<\/p>\n<p>Suppose you want to round all the values in the <code>wingspan<\/code> column in the <code>airplanes<\/code> table to whole numbers. To achieve this, you create the following <code>UPDATE<\/code> statement:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">UPDATE airplanes\r\nSET wingspan = ROUND(wingspan);<\/pre>\n<p>The <code>UPDATE<\/code> clause identifies <code>airplanes<\/code> as the target table, and the <code>SET<\/code> clause specifies that the values in the <code>wingspan<\/code> column should be rounded, which is achieved by using the built-in <code>ROUND<\/code> function.<\/p>\n<p>That\u2019s all it takes to update the <code>wingspan<\/code> data. However, there\u2019s a good chance that when you try to run this statement, you\u2019ll receive the following error:<\/p>\n<p><code>Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column. To disable safe mode, toggle the option in Preferences -&gt; SQL Editor and reconnect.<\/code><\/p>\n<p>By default, you cannot perform an update without a <code>WHERE<\/code> clause that specifies a key column. This helps to ensure that you don\u2019t make sweeping changes that you\u2019ll later regret. You can disable safe mode (as the error message suggests), either permanently or temporarily. I recommend that you do it on a temporary basis to avoid any unwanted changes elsewhere.<\/p>\n<p>To temporarily disable safe mode, use a <code>SET<\/code> statement to change the <code>SQL_SAFE_UPDATES<\/code> system variable to <code>0<\/code> prior to running your <code>UPDATE<\/code> statement and then set the variable to <code>1<\/code> after you run the statement, as shown in the following example:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SET SQL_SAFE_UPDATES = 0;\r\n\r\nUPDATE airplanes\r\nSET wingspan = ROUND(wingspan);\r\n\r\nSET SQL_SAFE_UPDATES = 1;<\/pre>\n<p>The <code>SET<\/code> statements merely toggle the variable off and then on during the current session. Be aware, however, that the <code>SET<\/code> statement supports the <code>GLOBAL<\/code> option, which sets a variable at the global scope. As a general practice, do <em>not<\/em> use this option when disabling safe updates. It is much less risky to make these sorts of changes at the session level to prevent any unplanned mishaps. Use <code>GLOBAL<\/code> only if it\u2019s essential in your circumstances.<\/p>\n<p>For more details on SET and global variables and settings. See <a href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/using-system-variables.html\">Using System Variables<\/a> in the MySQL Documentation.<\/p>\n<p>Even at the session level, the <code>SET<\/code> statement makes it possible to execute your <code>UPDATE<\/code> statement without generating an error. You can confirm the changes by running a simple <code>SELECT<\/code> statement after executing the script above:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SELECT * FROM airplanes;<\/pre>\n<p>Figure 1 shows part of the results returned by the <code>SELECT<\/code> statement. Notice that the <code>wingspan<\/code> values are now all whole numbers.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"2177\" height=\"865\" class=\"wp-image-94961\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2022\/10\/word-image-41.png\" \/> Figure 1. Rounding the values in the <code>wingspan<\/code> column<\/p>\n<p>In some cases, you might want to update multiple columns at the same time. For this, you need to add the additional column assignments, separating them with commas. For example, the following <code>UPDATE<\/code> statement modifies both the <code>wingspan<\/code> and <code>plane_length<\/code> columns:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SET SQL_SAFE_UPDATES = 0;\r\n\r\nUPDATE airplanes\r\nSET wingspan = ROUND(wingspan), plane_length = ROUND(plane_length);\r\n\r\nSET SQL_SAFE_UPDATES = 1;<\/pre>\n<p>Both column assignments work the same way. You\u2019re simply rounding the column values to whole numbers. If you were to query the <code>airplanes<\/code> table after running the <code>UPDATE<\/code> statement, your results would look similar to those shown in Figure 2.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"2200\" height=\"932\" class=\"wp-image-94962\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2022\/10\/word-image-42.png\" \/> Figure 2. Rounding the values in the <code>wingspan<\/code> and <code>plane_length<\/code> columns<\/p>\n<p>By using the <code>UPDATE<\/code> and <code>SET<\/code> clauses, you can quickly update all of a column\u2019s values. Just be careful if taking this approach. It\u2019s all too easy to mess things up in a big way.<\/p>\n<h2>Adding a <code><strong>WHERE<\/strong><\/code> clause to your <code><strong>UPDATE<\/strong><\/code> statement<\/h2>\n<p>Most of your <code>UPDATE<\/code> statements will likely include a <code>WHERE<\/code> clause to help you better target the data that you want to modify. The <code>WHERE<\/code> clause specifies one or more conditions that narrow down the rows to be updated. For example, the following statement includes a <code>WHERE<\/code> clause that limits the updates to rows with a <code>manufacturer_id<\/code> value of <code>1008<\/code>:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">UPDATE airplanes\r\nSET engine_type = 'piston (adg-i)' \r\nWHERE manufacturer_id = 1008;\r\n\r\nSELECT *\r\nFROM   airplanes\r\nWHERE manufacturer_id = 1008;<\/pre>\n<p>The <code>SET<\/code> clause in this statement sets the <code>engine_type<\/code> value to <code>piston<\/code> <code>(adg-i)<\/code> for the targeted rows. The results from executing the statements should look similar to Figure 3.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"1994\" height=\"332\" class=\"wp-image-94963\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2022\/10\/word-image-43.png\" \/> Figure 3. Limiting your update to specific rows<\/p>\n<p><strong>Note<\/strong>: In case you\u2019re wondering, the <code>adg-i<\/code> value is a reference to Airplane Design Group (ADG) classifications, a system used to categorize aircraft by dividing them into six groups based on their wingspans and tail heights. The lowercase <code>i<\/code> indicates that the planes in this example are in Group I. (I realize that you\u2019d probably want to add a column for the ADG groups. The approach I took here was meant only to demonstrate these concepts.)<\/p>\n<p>That said, it turns out that the B.206 airplane should actually be in Group II, which means you need to update that record without updating the others. Fortunately, you can define multiple conditions in your <code>WHERE<\/code> clause to help narrow down the rows. In the following example, the <code>WHERE<\/code> clause includes two conditions, one based on the <code>manufacturer_id<\/code> column and the other on the <code>plane<\/code> column:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">UPDATE airplanes\r\nSET engine_type = 'piston (adg-ii)'\r\nWHERE manufacturer_id = 1008 AND plane = 'B.206';<\/pre>\n<p>As in the previous example, the <code>WHERE<\/code> clause limits the updates to rows with a <code>manufacturer_id<\/code> value of <code>1008<\/code>. However, the clause also specifies that the <code>plane<\/code> value must equal <code>B.206<\/code>. The two conditions are linked together by the <code>AND<\/code> logical operator, which means that both conditions must evaluate to true for the row to be updated.<\/p>\n<p>After you run the <code>UPDATE<\/code> statement, you can retrieve the same rows as before. Your results should look similar to those shown in Figure 4. Notice that the B.206 aircraft is now shown as a Group II plane.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"2000\" height=\"330\" class=\"wp-image-94964\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2022\/10\/word-image-44.png\" \/> Figure 4. Limiting your update to one specific row<\/p>\n<p>You can make your <code>WHERE<\/code> clause as detailed as necessary to ensure that you\u2019re updating the target rows and no other rows. The key is to use your logical operators correctly to ensure that your conditional logic is accurate.<\/p>\n<h2>Working with column values<\/h2>\n<p>In the first example in this article, you saw how to use the <code>ROUND<\/code> system function to round values in the <code>airplanes<\/code> table. When you update a column in this way, MySQL uses the column\u2019s current value to create a new value. The ability to use the current value makes it possible to build on that value in ways that go beyond simply applying a function. For example, the following <code>UPDATE<\/code> statement adds 3 to the <code>wingspan<\/code> value and 5 to the <code>plane_length<\/code> value:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">UUPDATE airplanes \r\nSET wingspan = wingspan + 3, plane_length = plane_length + 5 \r\nWHERE plane_id = 344;<\/pre>\n<p>In this case, I used the <code>plane_id<\/code> value <code>344<\/code> in the <code>WHERE<\/code> clause, which I had to look up in the table. However, you might want to use a different method for finding this value, such as retrieving it through a subquery, a topic I plan to cover later in this series.<\/p>\n<p>After your run this statement, you can query the <code>airplanes<\/code> table to verify the results, which should look similar to those shown in Figure 5.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"2002\" height=\"332\" class=\"wp-image-94965\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2022\/10\/word-image-45.png\" \/> Figure 5. Increasing values in the <code>wingspan<\/code> and <code>plane_length<\/code> columns<\/p>\n<p>If you compare Figure 5 to Figure 4, you\u2019ll see that the row with a <code>plane_id<\/code> value of <code>344<\/code> has been updated. You might have also noticed that MySQL automatically updated the <code>parking_area<\/code> column, which is a generated column that multiples the <code>wingspan<\/code> and <code>plane_length<\/code> values.<\/p>\n<p>If you try to update a column with the same value it already has, MySQL is smart enough to realize the values are the same and does not change the original value. This approach could potentially reduce unnecessary overhead and minimize the impact on concurrent operations that might be trying to retrieve or modify that value at the same time. MySQL is also smart enough to recognize when you try to insert an unacceptable value into a column. For instance, the following <code>UPDATE<\/code> statement attempts to change the <code>engine_type<\/code> column to <code>NULL<\/code>:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">UPDATE airplanes SET engine_type = NULL WHERE plane_id = 344;<\/pre>\n<p>Because the column is defined as <code>NOT<\/code> <code>NULL<\/code>, the <code>UPDATE<\/code> statement will fail and generate the following error:<\/p>\n<p><code>Error Code: 1048. Column 'engine_type' cannot be null<\/code><\/p>\n<p>You\u2019ll also receive an error if you attempt to update a column to a value with an incorrect data type. For example, the following <code>UPDATE<\/code> statement attempts to update the <code>max_weight<\/code> column to the string value <code>unknown<\/code>:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">UPDATE airplanes\r\nSET max_weight = 'unknown'\r\nWHERE plane_id = 344;<\/pre>\n<p>Not surprisingly, this statement will also fail because the <code>max_weight<\/code> column is defined with the <code>MEDIUMINT<\/code> data type. Rather than update the value, MySQL returns the following error:<\/p>\n<p><code>Error Code: 1366. Incorrect integer value: 'unknown' for column 'max_weight' at row 1<\/code><\/p>\n<p>As with inserting data, updating data requires that you\u2019re familiar with the target columns whose values you\u2019re trying to modify. It\u2019s not enough just to know the data type. You must also understand how the data type is defined. For example, if you try to update the <code>icao_code<\/code> column with the string <code>abcdef<\/code>, you\u2019ll generate an error because the column is defined as <code>CHAR(4)<\/code>.<\/p>\n<h2>Updating foreign key columns in MySQL tables<\/h2>\n<p>There might be times when you want to update a value in a foreign key column. This can be tricky, however, because MySQL performs foreign key checks. For example, suppose you want to modify the <code>manufacturer_id<\/code> column in the <code>airplanes<\/code> table:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">UPDATE airplanes \r\nSET manufacturer_id = 2001\r\nWHERE manufacturer_id = 1008;<\/pre>\n<p>Not surprisingly, MySQL will balk when you try to run this statement and will instead return the following error (unless you\u2019ve included the <code>IGNORE<\/code> keyword:<\/p>\n<p><code>Error Code: 1452. Cannot add or update a child row: a foreign key constraint fails (`travel`.`airplanes`, CONSTRAINT `fk_manufacturer_id` FOREIGN KEY (`manufacturer_id`) REFERENCES `manufacturers` (`manufacturer_id`))<\/code><\/p>\n<p>You cannot update a foreign key to a value that does not exist in the referenced column. You must first make the necessary changes to the parent table. However, this too can be tricky. For example, you might try to modify the <code>manufacturer_id<\/code> value in the <code>manufacturers<\/code> table:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">UPDATE manufacturers \r\nSET manufacturer_id = 2001\r\nWHERE manufacturer_id = 1008;<\/pre>\n<p>Unfortunately, this too will cause MySQL to generate an error because you cannot update a value that\u2019s being referenced by a foreign key:<\/p>\n<p><code>Error Code: 1451. Cannot delete or update a parent row: a foreign key constraint fails (`travel`.`airplanes`, CONSTRAINT `fk_manufacturer_id` FOREIGN KEY (`manufacturer_id`) REFERENCES `manufacturers` (`manufacturer_id`))<\/code><\/p>\n<p>You can get around these issues by temporarily disabling foreign key checks within your session (or by setting the <code>CASCADE<\/code> option on the foreign key, something I\u2019ll be discussing in a later article). To achieve this, set the <code>foreign_key_checks<\/code> system variable to <code>0<\/code> before running the <code>UPDATE<\/code> statements, and then set it back to <code>1<\/code> after running the statements:<\/p>\n<pre class=\"lang:none theme:none\">SET foreign_key_checks = 0;\r\n\r\nUPDATE manufacturers \r\nSET manufacturer_id = 2001\r\nWHERE manufacturer_id = 1008;\r\n\r\nUPDATE airplanes \r\nSET manufacturer_id = 2001\r\nWHERE manufacturer_id = 1008;\r\n\r\nSET foreign_key_checks = 1;<\/pre>\n<p>In this way, you can update the <code>manufacturer_id<\/code> values in both tables without generating any foreign key errors. As a reminder, avoid using the <code>GLOBAL<\/code> option in your <code>SET<\/code> statement. If you turn off foreign key checks at a global level, you\u2019re putting the integrity of your data at risk.<\/p>\n<p>After you run these statements, you can query the <code>manufacturers<\/code> table to verify your changes:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\"><code>SELECT * FROM manufacturers WHERE manufacturer_id = 2001;<\/code><\/pre>\n<p>Figure 6 shows the data returned by this statement. As you can see, the table was updated with no problem, in part because you specified a new primary key value that did not already exist.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"1063\" height=\"217\" class=\"wp-image-94966\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2022\/10\/word-image-46.png\" \/> Figure 6. Updating the <code>manufacturers<\/code> table<\/p>\n<p>You can also query the <code>airplanes<\/code> table to verify that the rows have been properly updated:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SELECT * FROM airplanes WHERE manufacturer_id = 2001;<\/pre>\n<p>Figure 7 shows the results returned by the query. As expected, the <code>manufacturer_id<\/code> values have been updated in all the target rows.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"2006\" height=\"326\" class=\"wp-image-94967\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2022\/10\/word-image-47.png\" \/> Figure 7. Updating the <code>manufacturer_id<\/code> column in the <code>airplanes<\/code> table<\/p>\n<p>Chances are, you probably won\u2019t have to update foreign key columns too frequently, but it\u2019s good to understand what it takes to make it happen. Just know that there are other issues to be aware of, such as not trying to insert duplicate primary keys.<\/p>\n<h2>Updating primary key columns in MySQL tables<\/h2>\n<p>As with foreign keys, there might be times when you need to update the values in a primary key column. If you update a single value (as you saw above), it\u2019s usually no problem as long as the new value conforms to the column\u2019s requirements. However, things get trickier if updating multiple values at one time. For example, the following <code>UPDATE<\/code> statement attempts to add 1 to all <code>plane_id<\/code> values in rows that have a <code>manufacturer_id<\/code> value of <code>2001<\/code>:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">UPDATE airplanes \r\nSET plane_id = plane_id + 1\r\nWHERE manufacturer_id = 2001;<\/pre>\n<p>The statement has a good chance of failing because of the order that MySQL updates each row of data (although you can never be certain about the exact order that the database engine will choose when updating data). This is because MySQL is trying to update the original value to a value that already exists and is itself waiting to be updated. For instance, if MySQL tries to update the first row from <code>342<\/code> to <code>343<\/code> before the second row has been changed, the statement will fail and MySQL will return the following error:<\/p>\n<p><code>Error Code: 1062. Duplicate entry '343' for key 'airplanes.PRIMARY'<\/code><\/p>\n<p>You might be tempted to include the <code>IGNORE<\/code> keyword to try to get around this issue:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">UPDATE IGNORE airplanes \r\nSET plane_id = plane_id + 1\r\nWHERE manufacturer_id = 2001;<\/pre>\n<p>The <code>IGNORE<\/code> keyword instructs MySQL to return a warning rather than an error and to continue with the statement\u2019s execution instead of stopping. In this case, you\u2019ll likely receive four warnings, along with a message indicating only one row was successfully updated:<\/p>\n<p><code>1 row(s) affected, 4 warning(s):<\/code><\/p>\n<p><code>1062 Duplicate entry '343' for key 'airplanes.PRIMARY'<\/code><\/p>\n<p><code>1062 Duplicate entry '344' for key 'airplanes.PRIMARY'<\/code><\/p>\n<p><code>1062 Duplicate entry '345' for key 'airplanes.PRIMARY'<\/code><\/p>\n<p><code>1062 Duplicate entry '346' for key 'airplanes.PRIMARY'<\/code><\/p>\n<p><code>Rows matched: 5 Changed: 1 Warnings: 4<\/code><\/p>\n<p>If you query the <code>airplanes<\/code> table, you can see that only the last row has been updated, as shown in Figure 8. This is because the last row was the only one that did not try to update the primary key value to an existing value.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"2006\" height=\"324\" class=\"wp-image-94968\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2022\/10\/word-image-48.png\" \/> Figure 8. Using the <code>IGNORE<\/code> option when updating the <code>plane_id<\/code> column<\/p>\n<p>A better solution is to include an <code>ORDER<\/code> <code>BY<\/code> clause that sorts the rows by the <code>plane_id<\/code> values, in descending order:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">UPDATE airplanes \r\nSET plane_id = plane_id + 1\r\nWHERE manufacturer_id = 2001\r\nORDER BY plane_id DESC;<\/pre>\n<p>When you include the <code>ORDER<\/code> <code>BY<\/code> clause in this way, MySQL applies the updates starting with the last row, making it possible to increment the values by 1 without generating any errors or warnings.<\/p>\n<p>Figure 9 shows what the data now looks like after running the <code>UPDATE<\/code> statement.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"2008\" height=\"324\" class=\"wp-image-94969\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2022\/10\/word-image-49.png\" \/> Figure 9. Adding the <code>ORDER<\/code> <code>BY<\/code> clause to your <code>UPDATE<\/code> statement<\/p>\n<p>You probably won\u2019t need to use the <code>ORDER<\/code> <code>BY<\/code> clause very often, but when you do, it will prove very useful.<\/p>\n<p>Another clause that\u2019s similar in this respect is the <code>LIMIT<\/code> clause, which limits the number of rows that are updated. For instance, the following update statement limits the number of rows to <code>3<\/code>:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk \">UPDATE airplanes \r\nSET plane_id = plane_id + 1\r\nWHERE manufacturer_id = 2001\r\nORDER BY plane_id DESC\r\nLIMIT 3;<\/pre>\n<p>Because the <code>UPDATE<\/code> statement still includes the <code>ORDER<\/code> <code>BY<\/code> clause, the three rows that are updated start at the bottom and go up. Figure 10 shows the results of querying the table after the update.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"2000\" height=\"330\" class=\"wp-image-94970\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2022\/10\/word-image-50.png\" \/> Figure 10. Adding the <code>LIMIT<\/code> clause to your <code>UPDATE<\/code> statement<\/p>\n<p>I suspect you\u2019re not going to include the <code>LIMIT<\/code> clause in your <code>UPDATE<\/code> statements very often (if at all), but situations might arise in which you find it useful. For example, you might want to test an <code>UPDATE<\/code> statement that would normally modify a large number of rows. If you include the <code>LIMIT<\/code> clause while testing the statement, you\u2019ll reduce the amount of time and processing it takes to verify that the statement is working properly.<\/p>\n<h2>Working with the MySQL <code><strong>UPDATE<\/strong><\/code> statement<\/h2>\n<p>The <code>UPDATE<\/code> statement is one of the most common statements used when working with MySQL data. In most cases, you\u2019ll be including the <code>UPDATE<\/code>, <code>SET<\/code> and <code>WHERE<\/code> clauses. At times, you might forego the <code>WHERE<\/code> clause\u2014at your own peril\u2014and at other times, you might incorporate the <code>ORDER<\/code> <code>BY<\/code> clause or <code>LIMIT<\/code> clause (or both). However, the bulk of your updates will likely rely on the three primary clauses.<\/p>\n<p>Regardless of which clauses you use, you should understand how they all work to ensure that you\u2019re modifying your data as effectively as possible, while ensuring the accuracy of those updates. Fortunately, the <code>UPDATE<\/code> statement is fairly easy to understand and use, so you should have no problem getting started.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the previous two articles in this series, you learned about SELECT and INSERT, two important data manipulation language (DML) statements in MySQL. In this article, I focus on the UPDATE statement, another valuable DML statement in MySQL.&hellip;<\/p>\n","protected":false},"author":221841,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[53,145792],"tags":[],"coauthors":[6779],"class_list":["post-94959","post","type-post","status-publish","format-standard","hentry","category-featured","category-mysql"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/94959","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221841"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=94959"}],"version-history":[{"count":11,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/94959\/revisions"}],"predecessor-version":[{"id":94980,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/94959\/revisions\/94980"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=94959"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=94959"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=94959"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=94959"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}