From 992f7fcc753aeb90e33ddbac98573ae4b242cb08 Mon Sep 17 00:00:00 2001 From: babyfish-ct Date: Sat, 21 Dec 2024 03:56:55 +0800 Subject: [PATCH] Update more doc for MySQL batch problem --- .../association/classification.mdx | 420 ++++++++++++++++- docs/mutation/save-command/save-mode.mdx | 10 - .../association/classification.mdx | 423 ++++++++++++++++-- .../mutation/save-command/save-mode.mdx | 10 - 4 files changed, 796 insertions(+), 67 deletions(-) diff --git a/docs/mutation/save-command/association/classification.mdx b/docs/mutation/save-command/association/classification.mdx index 51f172828..c68ee0c6b 100644 --- a/docs/mutation/save-command/association/classification.mdx +++ b/docs/mutation/save-command/association/classification.mdx @@ -167,24 +167,103 @@ val book = Book { However, this is not mandatory. To make the example more universal, we don't assume that users have defined [IdView](../../../mapping/advanced/view/id-view) properties for entity types. All subsequent documentation will follow this approach without further reminders. ::: -Assuming the current database is H2, the generated SQL would be: +The generated SQL statements would be: 1. Save the aggregate root. - ```csharp + + + + ```sql merge into BOOK( NAME, EDITION, PRICE, STORE_ID + -- highlight-next-line ) key( NAME, EDITION - ) values(?, ?, ?, ?) - /* batch-0: [SQL in Action, 1, 39.9, 2] */ + ) values( + ? /* SQL in Action */, + ? /* 1 */, + ? /* 39.9 */, + ? /* 2 */ + ) ``` + + + + ```sql + insert into BOOK( + NAME, EDITION, PRICE, STORE_ID + ) values( + ? /* SQL in Action */, + ? /* 1 */, + ? /* 39.9 */, + ? /* 2 */ + -- highlight-next-line + ) on duplicate key update + /* fake update to return all ids */ ID = last_insert_id(ID), + PRICE = values(PRICE), + STORE_ID = values(STORE_ID) + ``` + + + + + ```sql + into into into BOOK( + NAME, EDITION, PRICE, STORE_ID + ) values( + ? /* SQL in Action */, + ? /* 1 */, + ? /* 39.9 */, + ? /* 2 */ + -- highlight-next-line + ) on conflict( + NAME, EDITION + ) do update set + PRICE = excluded.PRICE, + STORE_ID = excluded.STORE_ID + returning ID + ``` + + + + Since `Book.store` is a many-to-one relationship directly based on foreign key *(STORE_ID)*, the association between the current object and `BookStore(2)` object will be automatically created by the execution of this SQL. 2. If there are `Author` objects associated with the current object *(newly inserted data is `Book(100)`)* other than just `Author(4)` and `Author(5)`, break the associations with those other objects. - ```csharp + + + + ```sql + delete from BOOK_AUTHOR_MAPPING + where + BOOK_ID = ? /* 100 */ + and + not ( + AUTHOR_ID = any(? /* [4, 5] */) + ) + ``` + + + + + ```sql + delete from BOOK_AUTHOR_MAPPING + where + BOOK_ID = ? /* 100 */ + and + AUTHOR_ID not in( + ? /* 4 */, + ? /* 5 */ + ) + ``` + + + + + ```sql delete from BOOK_AUTHOR_MAPPING where BOOK_ID = ? /* 100 */ @@ -194,11 +273,19 @@ Assuming the current database is H2, the generated SQL would be: ) ``` - > This step is called unhooking, which will be introduced in subsequent documentation. Readers can ignore this for now. + + + + :::info + This step is called [Dissociation Operation](./dissociation), which will be introduced in subsequent documentation. Readers can ignore this for now. + ::: 3. Establish associations between the object *(newly inserted data is `Book(100)`)* and the two objects `Author(4)` and `Author(5)` - ```csharp + + + + ```sql merge into BOOK_AUTHOR_MAPPING tb_1_ using(values(?, ?)) tb_2_( BOOK_ID, AUTHOR_ID @@ -207,12 +294,64 @@ Assuming the current database is H2, the generated SQL would be: tb_1_.BOOK_ID = tb_2_.BOOK_ID and tb_1_.AUTHOR_ID = tb_2_.AUTHOR_ID - when not matched then insert(BOOK_ID, AUTHOR_ID) - values(tb_2_.BOOK_ID, tb_2_.AUTHOR_ID) + -- highlight-next-line + when not matched + then insert(BOOK_ID, AUTHOR_ID) + values(tb_2_.BOOK_ID, tb_2_.AUTHOR_ID) + /* batch-0: [100, 4] */ + /* batch-1: [100, 5] */ + ``` + + + + + :::caution + By default, MySQL does not enable batch operations and uses multiple SQL statements instead. + For specific details, please refer to [MySQL Issues](../mysql) + ::: + + 1. ```sql + insert + -- highlight-next-line + ignore + into BOOK_AUTHOR_MAPPING( + BOOK_ID, AUTHOR_ID + ) values( + ? /* 100 */, ? /* 4 */ + ) + ``` + + 2. ```sql + insert + -- highlight-next-line + ignore + into BOOK_AUTHOR_MAPPING( + BOOK_ID, AUTHOR_ID + ) values( + ? /* 100 */, ? /* 5 */ + ) + ``` + + + + + ```sql + insert into BOOK_AUTHOR_MAPPING( + BOOK_ID, AUTHOR_ID + ) values( + ?, ? + -- highlight-next-line + ) on conflict( + BOOK_ID, AUTHOR_ID + ) + do nothing /* batch-0: [100, 4] */ /* batch-1: [100, 5] */ ``` + + + :::info Through this example, it's not hard to see that short associations only create or destroy the association relationships between the current object and other objects, without further saving the associated objects. @@ -482,13 +621,20 @@ This operation generates two SQL statements: ```csharp insert into order_( PROVINCE, CITY, ADDRESS, CUSTOMER_ID - ) values(?, ?, ?, ?) - /*batch-0: [Prenzlauer Berg, Berlin, Brandenburgische Straße 9, Prenzlauer Berg, Berlin, Germany, 1] */ + ) values( + ? /* Prenzlauer Berg */, + ? /* Berlin */, + ? /* Brandenburgische Strae 9, Prenzlauer Berg, Berlin, Germany */, + ? /* 1 */ + ) ``` 2. Insert all child objects `OrderItem` - ```csharp + + + + ```sql insert into ORDER_ITEM( ORDER_ID, PRODUCT_ID, @@ -498,6 +644,41 @@ This operation generates two SQL statements: /* batch-1: [100, 9, 1] */ ``` + + + + :::caution + By default, MySQL does not enable batch operations and uses multiple SQL statements instead. + For specific details, please refer to [MySQL Issues](../mysql) + ::: + + 1. ```sql + insert into ORDER_ITEM( + ORDER_ID, + PRODUCT_ID, + QUANTITY + ) values( + ? /* 100 */, + ? /* 8 */, + ? /* 2 */ + ) + ``` + + 2. ```sql + insert into ORDER_ITEM( + ORDER_ID, + PRODUCT_ID, + QUANTITY + ) values( + ? /* 100 */, + ? /* 9 */, + ? /* 1 */ + ) + ``` + + + + :::info As we can see, long associations not only modify the association relationship between the current object and other objects but also cause the associated objects to be saved. @@ -549,24 +730,116 @@ Taking H2 as an example, it generates two SQL statements: 1. First save the associated object `BookStore` - ```csharp + + + + ```sql merge into BOOK_STORE( NAME, WEBSITE - ) key(NAME) values(?, ?) - /* batch-0: [TURING, https://www.turing.com] */ + -- highlight-next-line + ) key( + NAME + ) values( + ? /* TURING */, + ? /* https://www.turing.com */ + ) ``` + + + + ```sql + insert into BOOK_STORE( + NAME, WEBSITE + ) values( + ? /* TURING */, + ? /* https://www.turing.com */ + -- highlight-next-line + ) on duplcate update + /* fake update to return all ids */ ID = last_insert_id(ID), + WEBSITE = VALUES(WEBSITE) + ``` + + + + + ```sql + insert into BOOK_STORE( + NAME, WEBSITE + ) values( + ? /* TURING */, + ? /* https://www.turing.com */ + -- highlight-next-line + ) on conflict( + NAME, WEBSITE + ) do update set + WEBSITE = excluded.WEBSITE, + return ID + ``` + + + + 2. Then save the current object `Book` - ```csharp + + + + ```sql merge into BOOK( NAME, EDITION, PRICE, STORE_ID + --highlight-next-line ) key( NAME, EDITION - ) values(?, ?, ?, ?) - /* batch-0: [SQL in Action, 1, 49.9, 100] */ + ) values( + ? /* SQL in Action */, + ? /* 1 */, + ? /* 49.9 */, + ? /* 100 */ + ) + ``` + + + + + ```sql + insert into BOOK( + NAME, EDITION, PRICE, STORE_ID + ) values( + ? /* SQL in Action */, + ? /* 1 */, + ? /* 49.9 */, + ? /* 100 */ + -- highlight-next-line + ) on duplcate key update + /* fake update to return all ids */ ID = last_insert_id(ID), + PRICE = values(PRICE), + STORE_ID = values(STORE_ID) + ``` + + + + + ```sql + insert into BOOK( + NAME, EDITION, PRICE, STORE_ID + ) values( + ? /* SQL in Action */, + ? /* 1 */, + ? /* 49.9 */, + ? /* 100 */ + -- highlight-next-line + ) on conflict( + NAME, EDITION + ) do update set + PRICE = values(PRICE), + STORE_ID = values(STORE_ID) + returning ID ``` + + + :::caution When discussing forward associations in work communication, it's recommended to use expressions like "current object/associated object" rather than "parent object/child object". @@ -640,20 +913,65 @@ Taking H2 as an example, it generates three SQL statements: 1. First save the current object `BookStore` - ```csharp + + + + ```sql merge into BOOK_STORE( NAME, WEBSITE + -- highlight-next-line ) key( NAME - ) values(?, ?) - /* batch-0: [TURING, https://www.turing.com] */ + ) values( + ? /* TURING */, + ? /* https://www.turing.com */ + ) ``` + + + + ```sql + insert into BOOK_STORE( + NAME, WEBSITE + ) values( + ? /* TURING */, + ? /* https://www.turing.com */ + -- highlight-next-line + ) on duplcate update + /* fake update to return all ids */ ID = last_insert_id(ID), + WEBSITE = VALUES(WEBSITE) + ``` + + + + + ```sql + insert into BOOK_STORE( + NAME, WEBSITE + ) values( + ? /* TURING */, + ? /* https://www.turing.com */ + -- highlight-next-line + ) on conflict( + NAME, WEBSITE + ) do update set + WEBSITE = excluded.WEBSITE, + return ID + ``` + + + + 2. Then save the associated objects `Book` - ```csharp + + + + ```sql merge into BOOK( NAME, EDITION, PRICE, STORE_ID + -- highlight-next-line ) key( NAME, EDITION ) values(?, ?, ?, ?) @@ -661,6 +979,64 @@ Taking H2 as an example, it generates three SQL statements: /* batch-1: [RUST programming, 2, 39.9, 100] */ ``` + + + + :::caution + By default, MySQL does not enable batch operations and uses multiple SQL statements instead. + For specific details, please refer to [MySQL Issues](../mysql) + ::: + + 1. ```sql + insert into BOOK( + NAME, EDITION, PRICE, STORE_ID + ) values( + ? /* SQL in Action */, + ? /* 1 */, + ? /* 49.9 */, + ? /* 100 */ + -- highlight-next-line + ) on duplcate update + /* fake update to return all ids */ ID = last_insert_id(ID), + PRICE = VALUES(PRICE), + STORE_ID = VALUES(STORE_ID) + + 2. ```sql + insert into BOOK( + NAME, EDITION, PRICE, STORE_ID + ) values( + ? /* RUST programming */, + ? /* 2 */, + ? /* 39.9 */, + ? /* 100 */ + -- highlight-next-line + ) on duplcate update + /* fake update to return all ids */ ID = last_insert_id(ID), + PRICE = VALUES(PRICE), + STORE_ID = VALUES(STORE_ID) + ``` + + + + + ```sql + insert into BOOK( + NAME, EDITION, PRICE, STORE_ID + ) values( + ?, ?, ?, ? + -- highlight-next-line + ) on conflict( + NAME, EDITION + ) do update set + PRICE = excluded.PRICE, + STORE_ID = excluded.STORE_ID + /* batch-0: [SQL in Action, 1, 49.9, 100] */ + /* batch-1: [RUST programming, 2, 39.9, 100] */ + ``` + + + + 3. The third SQL statement is not relevant to the topic being discussed here, so it's omitted :::info diff --git a/docs/mutation/save-command/save-mode.mdx b/docs/mutation/save-command/save-mode.mdx index 665147b0e..242547304 100644 --- a/docs/mutation/save-command/save-mode.mdx +++ b/docs/mutation/save-command/save-mode.mdx @@ -973,8 +973,6 @@ For specific details, please refer to [MySQL Issues](./mysql) ) on duplicate key update /* fake update to return all ids */ ID = last_insert_id(ID), - NAME = values(NAME), - EDITION = values(EDITION), PRICE = values(PRICE), STORE_ID = values(STORE_ID) ``` @@ -990,8 +988,6 @@ For specific details, please refer to [MySQL Issues](./mysql) ) on duplicate key update /* fake update to return all ids */ ID = last_insert_id(ID), - NAME = values(NAME), - EDITION = values(EDITION), PRICE = values(PRICE), STORE_ID = values(STORE_ID) ``` @@ -1007,8 +1003,6 @@ For specific details, please refer to [MySQL Issues](./mysql) ) on duplicate key update /* fake update to return all ids */ ID = last_insert_id(ID), - NAME = values(NAME), - EDITION = values(EDITION), PRICE = values(PRICE), STORE_ID = values(STORE_ID) ``` @@ -1024,8 +1018,6 @@ For specific details, please refer to [MySQL Issues](./mysql) ) on duplicate key update /* fake update to return all ids */ ID = last_insert_id(ID), - NAME = values(NAME), - EDITION = values(EDITION), PRICE = values(PRICE), STORE_ID = values(STORE_ID) ``` @@ -1041,8 +1033,6 @@ on conflict( /* highlight-next-line */ NAME, EDITION ) do update set - NAME = excluded.NAME, - EDITION = excluded.EDITION, PRICE = excluded.PRICE, STORE_ID = excluded.STORE_ID returning ID diff --git a/i18n/zh/docusaurus-plugin-content-docs/current/mutation/save-command/association/classification.mdx b/i18n/zh/docusaurus-plugin-content-docs/current/mutation/save-command/association/classification.mdx index d677c5e59..9a591d13d 100644 --- a/i18n/zh/docusaurus-plugin-content-docs/current/mutation/save-command/association/classification.mdx +++ b/i18n/zh/docusaurus-plugin-content-docs/current/mutation/save-command/association/classification.mdx @@ -167,24 +167,103 @@ val book = Book { 但这并不是必须的,为了让例子更具普适性,这里并不假设用户为实体类型定义了[IdView](../../../mapping/advanced/view/id-view)属性。后续所有文档都如此,不再提醒。 ::: -假设当前数据库为H2,生成的SQL +生成如下SQL 1. 保存聚合根。 - ```csharp + + + + ```sql merge into BOOK( NAME, EDITION, PRICE, STORE_ID + -- highlight-next-line ) key( NAME, EDITION - ) values(?, ?, ?, ?) - /* batch-0: [SQL in Action, 1, 39.9, 2] */ + ) values( + ? /* SQL in Action */, + ? /* 1 */, + ? /* 39.9 */, + ? /* 2 */ + ) + ``` + + + + + ```sql + insert into BOOK( + NAME, EDITION, PRICE, STORE_ID + ) values( + ? /* SQL in Action */, + ? /* 1 */, + ? /* 39.9 */, + ? /* 2 */ + -- highlight-next-line + ) on duplicate key update + /* fake update to return all ids */ ID = last_insert_id(ID), + PRICE = values(PRICE), + STORE_ID = values(STORE_ID) + ``` + + + + + ```sql + into into into BOOK( + NAME, EDITION, PRICE, STORE_ID + ) values( + ? /* SQL in Action */, + ? /* 1 */, + ? /* 39.9 */, + ? /* 2 */ + -- highlight-next-line + ) on conflict( + NAME, EDITION + ) do update set + PRICE = excluded.PRICE, + STORE_ID = excluded.STORE_ID + returning ID ``` + + + 由于`Book.store`是直接基于外键 *(STORE_ID)* 的多对一关系,当前对象和`BookStore(2)`对象的关联将会因这条SQL的执行而被自动创建。 2. 如果和当前对象 *(新插入的数据为`Book(100)`)* 关联的`Author`对象不仅仅只有`Author(4)`和`Author(5)`,切断和其他对象啊的关联。 - ```csharp + + + + ```sql + delete from BOOK_AUTHOR_MAPPING + where + BOOK_ID = ? /* 100 */ + and + not ( + AUTHOR_ID = any(? /* [4, 5] */) + ) + ``` + + + + + ```sql + delete from BOOK_AUTHOR_MAPPING + where + BOOK_ID = ? /* 100 */ + and + AUTHOR_ID not in( + ? /* 4 */, + ? /* 5 */ + ) + ``` + + + + + ```sql delete from BOOK_AUTHOR_MAPPING where BOOK_ID = ? /* 100 */ @@ -194,11 +273,19 @@ val book = Book { ) ``` - > 这个步骤叫做脱勾,后续文档会给予介绍,这里请读者先行忽略 + + + + :::info + 这个步骤叫做[脱勾操作](./dissociation),后续文档会给予介绍,这里请读者先行忽略 + ::: 3. 建立对象 *(新插入的数据为`Book(100)`)* 和`Author(4)`和`Author(5)`两个对象之间的关联 - ```csharp + + + + ```sql merge into BOOK_AUTHOR_MAPPING tb_1_ using(values(?, ?)) tb_2_( BOOK_ID, AUTHOR_ID @@ -207,12 +294,63 @@ val book = Book { tb_1_.BOOK_ID = tb_2_.BOOK_ID and tb_1_.AUTHOR_ID = tb_2_.AUTHOR_ID - when not matched then insert(BOOK_ID, AUTHOR_ID) - values(tb_2_.BOOK_ID, tb_2_.AUTHOR_ID) + -- highlight-next-line + when not matched + then insert(BOOK_ID, AUTHOR_ID) + values(tb_2_.BOOK_ID, tb_2_.AUTHOR_ID) + /* batch-0: [100, 4] */ + /* batch-1: [100, 5] */ + ``` + + + + + :::caution + 默认情况下,MySQL不会启用批量操作,而采用多条SQL。具体细节请参考[MySQL的问题](../mysql) + ::: + + 1. ```sql + insert + -- highlight-next-line + ignore + into BOOK_AUTHOR_MAPPING( + BOOK_ID, AUTHOR_ID + ) values( + ? /* 100 */, ? /* 4 */ + ) + ``` + + 2. ```sql + insert + -- highlight-next-line + ignore + into BOOK_AUTHOR_MAPPING( + BOOK_ID, AUTHOR_ID + ) values( + ? /* 100 */, ? /* 5 */ + ) + ``` + + + + + ```sql + insert into BOOK_AUTHOR_MAPPING( + BOOK_ID, AUTHOR_ID + ) values( + ?, ? + -- highlight-next-line + ) on conflict( + BOOK_ID, AUTHOR_ID + ) + do nothing /* batch-0: [100, 4] */ /* batch-1: [100, 5] */ ``` + + + :::info 通过此例,不难发现,短关联只会创建或销毁当前对象和其他对象之间的关联关系,不会进一步保存关联对象。 @@ -474,16 +612,23 @@ sqlClient.insert(order) 1. 插入根对象`Order` - ```csharp + ```sql insert into order_( PROVINCE, CITY, ADDRESS, CUSTOMER_ID - ) values(?, ?, ?, ?) - /*batch-0: [四川, 成都, 龙泉驿区洪玉路与十洪路交叉口, 1] */ + ) values( + ? /* 四川 */, + ? /* 成都 */, + ? /* 龙泉驿区洪玉路与十洪路交叉口 */, + ? /* 1 */ + ) ``` 2. 插入所有子对象`OrderItem` - ```csharp + + + + ```sql insert into ORDER_ITEM( ORDER_ID, PRODUCT_ID, @@ -493,6 +638,40 @@ sqlClient.insert(order) /* batch-1: [100, 9, 1] */ ``` + + + + :::caution + 默认情况下,MySQL不会启用批量操作,而采用多条SQL。具体细节请参考[MySQL的问题](../mysql) + ::: + + 1. ```sql + insert into ORDER_ITEM( + ORDER_ID, + PRODUCT_ID, + QUANTITY + ) values( + ? /* 100 */, + ? /* 8 */, + ? /* 2 */ + ) + ``` + + 2. ```sql + insert into ORDER_ITEM( + ORDER_ID, + PRODUCT_ID, + QUANTITY + ) values( + ? /* 100 */, + ? /* 9 */, + ? /* 1 */ + ) + ``` + + + + :::info 由此可见,长关联不仅能修改当前对象和其他对象的关联关系,还是会导致关联对象被保存。 @@ -544,24 +723,116 @@ sqlClient.save(book) 1. 先保存关联对象`BookStore` - ```csharp + + + + ```sql merge into BOOK_STORE( NAME, WEBSITE - ) key(NAME) values(?, ?) - /* batch-0: [TURING, https://www.turing.com] */ + -- highlight-next-line + ) key( + NAME + ) values( + ? /* TURING */, + ? /* https://www.turing.com */ + ) + ``` + + + + + ```sql + insert into BOOK_STORE( + NAME, WEBSITE + ) values( + ? /* TURING */, + ? /* https://www.turing.com */ + -- highlight-next-line + ) on duplcate update + /* fake update to return all ids */ ID = last_insert_id(ID), + WEBSITE = VALUES(WEBSITE) + ``` + + + + + ```sql + insert into BOOK_STORE( + NAME, WEBSITE + ) values( + ? /* TURING */, + ? /* https://www.turing.com */ + -- highlight-next-line + ) on conflict( + NAME, WEBSITE + ) do update set + WEBSITE = excluded.WEBSITE, + return ID ``` -2. 后保存当前对象`Book` + + + +2. 后保存当前对象`Book` *(假设上个操作返回的id为`100`)* - ```csharp + + + + ```sql merge into BOOK( NAME, EDITION, PRICE, STORE_ID + --highlight-next-line ) key( NAME, EDITION - ) values(?, ?, ?, ?) - /* batch-0: [SQL in Action, 1, 49.9, 100] */ + ) values( + ? /* SQL in Action */, + ? /* 1 */, + ? /* 49.9 */, + ? /* 100 */ + ) + ``` + + + + + ```sql + insert into BOOK( + NAME, EDITION, PRICE, STORE_ID + ) values( + ? /* SQL in Action */, + ? /* 1 */, + ? /* 49.9 */, + ? /* 100 */ + -- highlight-next-line + ) on duplcate key update + /* fake update to return all ids */ ID = last_insert_id(ID), + PRICE = values(PRICE), + STORE_ID = values(STORE_ID) + ``` + + + + + ```sql + insert into BOOK( + NAME, EDITION, PRICE, STORE_ID + ) values( + ? /* SQL in Action */, + ? /* 1 */, + ? /* 49.9 */, + ? /* 100 */ + -- highlight-next-line + ) on conflict( + NAME, EDITION + ) do update set + PRICE = values(PRICE), + STORE_ID = values(STORE_ID) + returning ID ``` + + + :::caution 在工作交流中,面对前置关联时,建议用"当前对象/关联对象"这样的方式来表达,而不是"父对象/子对象"这种表达方式。 @@ -635,20 +906,65 @@ sqlClient.save(store) { 1. 先保存当前对象`BookStore` - ```csharp + + + + ```sql merge into BOOK_STORE( NAME, WEBSITE + -- highlight-next-line ) key( NAME - ) values(?, ?) - /* batch-0: [TURING, https://www.turing.com] */ + ) values( + ? /* TURING */, + ? /* https://www.turing.com */ + ) + ``` + + + + + ```sql + insert into BOOK_STORE( + NAME, WEBSITE + ) values( + ? /* TURING */, + ? /* https://www.turing.com */ + -- highlight-next-line + ) on duplcate update + /* fake update to return all ids */ ID = last_insert_id(ID), + WEBSITE = VALUES(WEBSITE) + ``` + + + + + ```sql + insert into BOOK_STORE( + NAME, WEBSITE + ) values( + ? /* TURING */, + ? /* https://www.turing.com */ + -- highlight-next-line + ) on conflict( + NAME, WEBSITE + ) do update set + WEBSITE = excluded.WEBSITE, + return ID ``` -2. 后保存关联对象`Book` + + + +2. 后保存关联对象`Book` *(假设上个操作返回的id为`100`)* - ```csharp + + + + ```sql merge into BOOK( NAME, EDITION, PRICE, STORE_ID + -- highlight-next-line ) key( NAME, EDITION ) values(?, ?, ?, ?) @@ -656,6 +972,63 @@ sqlClient.save(store) { /* batch-1: [RUST programming, 2, 39.9, 100] */ ``` + + + + :::caution + 默认情况下,MySQL不会启用批量操作,而采用多条SQL。具体细节请参考[MySQL的问题](../mysql) + ::: + + 1. ```sql + insert into BOOK( + NAME, EDITION, PRICE, STORE_ID + ) values( + ? /* SQL in Action */, + ? /* 1 */, + ? /* 49.9 */, + ? /* 100 */ + -- highlight-next-line + ) on duplcate update + /* fake update to return all ids */ ID = last_insert_id(ID), + PRICE = VALUES(PRICE), + STORE_ID = VALUES(STORE_ID) + + 2. ```sql + insert into BOOK( + NAME, EDITION, PRICE, STORE_ID + ) values( + ? /* RUST programming */, + ? /* 2 */, + ? /* 39.9 */, + ? /* 100 */ + -- highlight-next-line + ) on duplcate update + /* fake update to return all ids */ ID = last_insert_id(ID), + PRICE = VALUES(PRICE), + STORE_ID = VALUES(STORE_ID) + ``` + + + + + ```sql + insert into BOOK( + NAME, EDITION, PRICE, STORE_ID + ) values( + ?, ?, ?, ? + -- highlight-next-line + ) on conflict( + NAME, EDITION + ) do update set + PRICE = excluded.PRICE, + STORE_ID = excluded.STORE_ID + /* batch-0: [SQL in Action, 1, 49.9, 100] */ + /* batch-1: [RUST programming, 2, 39.9, 100] */ + ``` + + + + 3. 第三条SQL和这里讨论的话题无关,省略 :::info diff --git a/i18n/zh/docusaurus-plugin-content-docs/current/mutation/save-command/save-mode.mdx b/i18n/zh/docusaurus-plugin-content-docs/current/mutation/save-command/save-mode.mdx index 87e3345ca..d9b9c2dc9 100644 --- a/i18n/zh/docusaurus-plugin-content-docs/current/mutation/save-command/save-mode.mdx +++ b/i18n/zh/docusaurus-plugin-content-docs/current/mutation/save-command/save-mode.mdx @@ -958,8 +958,6 @@ merge into BOOK( ) on duplicate key update /* fake update to return all ids */ ID = last_insert_id(ID), - NAME = values(NAME), - EDITION = values(EDITION), PRICE = values(PRICE), STORE_ID = values(STORE_ID) ``` @@ -975,8 +973,6 @@ merge into BOOK( ) on duplicate key update /* fake update to return all ids */ ID = last_insert_id(ID), - NAME = values(NAME), - EDITION = values(EDITION), PRICE = values(PRICE), STORE_ID = values(STORE_ID) ``` @@ -992,8 +988,6 @@ merge into BOOK( ) on duplicate key update /* fake update to return all ids */ ID = last_insert_id(ID), - NAME = values(NAME), - EDITION = values(EDITION), PRICE = values(PRICE), STORE_ID = values(STORE_ID) ``` @@ -1009,8 +1003,6 @@ merge into BOOK( ) on duplicate key update /* fake update to return all ids */ ID = last_insert_id(ID), - NAME = values(NAME), - EDITION = values(EDITION), PRICE = values(PRICE), STORE_ID = values(STORE_ID) ``` @@ -1026,8 +1018,6 @@ on conflict( -- highlight-next-line NAME, EDITION ) do update set - NAME = excluded.NAME, - EDITION = excluded.EDITION, PRICE = excluded.PRICE, STORE_ID = excluded.STORE_ID returning ID