developer tip

업데이트 부분에서 새 값과 이전 값을 모두 사용할 수 있도록 UPSERT를 수행하는 방법

copycodes 2020. 11. 23. 08:19
반응형

업데이트 부분에서 새 값과 이전 값을 모두 사용할 수 있도록 UPSERT를 수행하는 방법


어리석지 만 간단한 예 :받은 항목의 합계를 보관하는 테이블 '항목'이 있다고 가정합니다.

Item_Name              Items_In_Stock

여기서 항목 이름은 기본 키입니다. 수량 X의 품목 A를받을 때 다음을 달성하는 방법.

항목이 존재하지 않는 경우 항목 A에 대한 새 리 코어를 삽입하고 재고 항목을 X로 설정하고 재고 항목이 Y 인 레코드가있는 경우 재고 항목의 새 값은 (X + Y)입니다.

INSERT INTO `item`
(`item_name`, items_in_stock)
VALUES( 'A', 27)
ON DUPLICATE KEY UPDATE
`new_items_count` = 27 + (SELECT items_in_stock where item_name = 'A' )

내 문제는 실제 테이블에 여러 열이 있다는 것입니다. 업데이트 부분에 여러 개의 select 문을 작성하는 것이 좋은 생각입니까?

물론 코드로 할 수 있지만 더 좋은 방법이 있습니까?


내 의견에서 언급했듯이 ON DUPLICATE KEY를 발생시키는 행을 참조하기 위해 하위 선택을 수행 할 필요가 없습니다. 따라서 귀하의 예에서 다음을 사용할 수 있습니다.

INSERT INTO `item`
(`item_name`, items_in_stock)
VALUES( 'A', 27)
ON DUPLICATE KEY UPDATE
`new_items_count` = `new_items_count` + 27

대부분의 일은 정말 간단하다는 것을 기억하십시오. 단순해야하는 무언가를 지나치게 복잡하게 만드는 것은 잘못된 방식으로 수행 할 가능성이 높습니다. :)


이 예제에서 아이디어를 얻을 수 있습니다.

사용자 현명한 7 일 데이터를 추가한다고 가정 해 보겠습니다.

사용자 ID 및 요일에 대해 고유 한 값이 있어야합니다.

UNIQUE KEY `seven_day` (`userid`,`day`)

여기 테이블이 있습니다

CREATE TABLE `table_name` (
  `userid` char(4) NOT NULL,
  `day` char(3) NOT NULL,
  `open` char(5) NOT NULL,
  `close` char(5) NOT NULL,
  UNIQUE KEY `seven_day` (`userid`,`day`)
);

그리고 귀하의 쿼리는

INSERT INTO table_name (userid,day,open,close) 
    VALUES ('val1', 'val2','val3','val4') 
        ON DUPLICATE KEY UPDATE open='val3', close='val4';

예:

<?php
//If your data is
$data= array(
        'sat'=>array("userid"=>"1001", "open"=>"01.01", "close"=>"11.01"),
        'sun'=>array("userid"=>"1001", "open"=>"02.01", "close"=>"22.01"),
        'sat'=>array("userid"=>"1001", "open"=>"03.01", "close"=>"33.01"),
        'mon'=>array("userid"=>"1002", "open"=>"08.01", "close"=>"08.01"),
        'mon'=>array("userid"=>"1002", "open"=>"07.01", "close"=>"07.01")
    );


//If you query this in a loop
//$conn = mysql_connect("localhost","root","");
//mysql_select_db("test", $conn);

foreach($data as $day=>$info) {
    $sql = "INSERT INTO table_name (userid,day,open,close) 
                VALUES ('$info[userid]', '$day','$info[open]','$info[close]') 
            ON DUPLICATE KEY UPDATE open='$info[open]', close='$info[close]'";
    mysql_query($sql);
}
?>

데이터는 테이블에 있습니다.

+--------+-----+-------+-------+
| userid | day | open  | close |
+--------+-----+-------+-------+
| 1001   | sat | 03.01 | 33.01 |
| 1001   | sun | 02.01 | 22.01 |
| 1002   | mon | 07.01 | 07.01 |
+--------+-----+-------+-------+

Michael의 대답이 옳지 만 프로그래밍 방식으로 upsert를 수행하려면 조금 더 알아야합니다.

먼저 테이블을 만들고 고유 인덱스를 원하는 열을 지정합니다.

CREATE TABLE IF NOT EXISTS Cell (
  cellId BIGINT UNSIGNED,
  attributeId BIGINT UNSIGNED,
  entityRowId BIGINT UNSIGNED,
  value DECIMAL(25,5),
  UNIQUE KEY `id_ce` (`cellId`,`entityRowId`)
)

그런 다음 여기에 몇 가지 값을 삽입합니다.

INSERT INTO Cell VALUES( 1, 6, 199, 1.0 );

Try doing the same thing again, and you'll get a duplicate key error, because cellId and entityRowId are same:

INSERT INTO Cell VALUES( 1, 6, 199, 1.0 );

Duplicate entry '1-199' for key 'id_ce'

That's why we use the upsert command:

INSERT INTO Cell ( cellId, attributeId, entityRowId, value)
VALUES( 1, 6, 199, 300.0 )
ON DUPLICATE KEY UPDATE `value` = `value` + VALUES(`value`)

This command takes the value 1.0 that's already there as value and does a value = value + 300.0.

So even after executing the above command, there will be only one row in the table, and the value will be 301.0.


This is the syntax for an upsert

INSERT INTO `{TABLE}` (`{PKCOLUMN}`, `{COLUMN}`) VALUES (:value)
ON DUPLICATE KEY UPDATE `{COLUMN}` = :value_dup';

If you have value for PK Column, or Unique Index on a column which satisfies unicity, You can use INSERT IGNORE, INSERT INTO ... ON DUPLICATE, or REPLACE

Example with INSERT IGNORE

INSERT IGNORE INTO Table1
    (ID, serverID, channelID, channelROLE)
VALUES
    (....);

Example with INSERT INTO .. ON DUPLICATE KEY UPDATE

SET @id = 1,
    @serverId = 123545,
    @channelId = 512580,
    @channelRole = 'john';
INSERT INTO Table1
    (ID, serverID, channelID, channelROLE)
VALUES
    (@id, @serverId, @channelId, @channelRole)
ON DUPLICATE KEY UPDATE
    serverId = @serverId,
    channelId = @channelId,
    channelRole = @channelRole;

Example with Replace

REPLACE INTO table1
    (ID, serverID, channelID, channelROLE)
VALUES
    (...);

참고URL : https://stackoverflow.com/questions/6107752/how-to-perform-an-upsert-so-that-i-can-use-both-new-and-old-values-in-update-par

반응형