[mysql] MySQL에 ‘존재하지 않는 경우 삽입’하는 방법?

인터넷 검색으로 시작하여 뮤텍스 테이블에 대해 이야기하는 이 기사 를 찾았습니다 .

~ 1400 만 개의 레코드가있는 테이블이 있습니다. 동일한 형식으로 더 많은 데이터를 추가하려면 한 쌍의 쿼리를 사용하지 않고 삽입하려는 레코드가 없는지 확인하는 방법이 있습니까? 빈)?

unique필드에 대한 제약 insert이 이미 존재하는 경우 실패를 보장 합니까?

PHP를 통해 삽입을 발행하면 스크립트가 잠기는 것처럼 단지 제약 조건 이있는 것 같습니다 .



답변

사용하다 INSERT IGNORE INTO table

http://bogdan.org.ua/2007/10/18/mysql-insert-if-not-exists-syntax.html 참조

INSERT … ON DUPLICATE KEY UPDATE구문 도 있습니다. dev.mysql.com에서 설명을 찾을 수 있습니다.


Google의 웹 캐시에 따라 bogdan.org.ua에서 게시 :

2007 년 10 월 18 일

시작하려면 : 최신 MySQL부터는 제목에 표시된 구문이 불가능합니다. 그러나 기존 기능을 사용하여 예상되는 것을 달성하는 매우 쉬운 방법이 몇 가지 있습니다.

중복 키 업데이트에 INSERT IGNORE, REPLACE 또는 INSERT…

테이블이 있다고 상상해보십시오.

CREATE TABLE `transcripts` (
`ensembl_transcript_id` varchar(20) NOT NULL,
`transcript_chrom_start` int(10) unsigned NOT NULL,
`transcript_chrom_end` int(10) unsigned NOT NULL,
PRIMARY KEY (`ensembl_transcript_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

이제 Ensembl에서 자동 메타 데이터 가져 오기 스크립트 메타 데이터를 파이프 라인에 가져오고 여러 가지 이유로 파이프 라인이 실행 단계에서 중단 될 수 있다고 상상해보십시오. 따라서 우리는 두 가지를 보장해야합니다.

  1. 파이프 라인을 반복해서 실행해도 데이터베이스가 손상되지 않습니다

  2. ‘중복 키’오류로 인해 반복 된 실행이 종료되지 않습니다.

방법 1 : REPLACE 사용

매우 간단합니다.

REPLACE INTO `transcripts`
SET `ensembl_transcript_id` = 'ENSORGT00000000001',
`transcript_chrom_start` = 12345,
`transcript_chrom_end` = 12678;

레코드가 있으면 덮어 씁니다. 아직 존재하지 않으면 작성됩니다. 그러나이 방법을 사용하는 것은 효율적이지 않습니다. 기존 레코드를 덮어 쓸 필요가 없으며 그냥 건너 뛰는 것이 좋습니다.

방법 2 : INSERT IGNORE 사용하기 매우 간단합니다.

INSERT IGNORE INTO `transcripts`
SET `ensembl_transcript_id` = 'ENSORGT00000000001',
`transcript_chrom_start` = 12345,
`transcript_chrom_end` = 12678;

여기서 ‘ensembl_transcript_id’가 데이터베이스에 이미 존재하면 자동으로 건너 뜁니다 (무시). (더 정확하게 말하면, MySQL 참조 매뉴얼에서 인용 한 내용은 다음과 같습니다.“IGNORE 키워드를 사용하는 경우 INSERT 문을 실행하는 동안 발생하는 오류는 대신 경고로 처리됩니다. 예를 들어 IGNORE가 없으면 기존 UNIQUE 인덱스를 복제하는 행 또는 테이블의 PRIMARY KEY 값으로 인해 중복 키 오류가 발생하고 명령문이 중단됩니다.”) 레코드가 아직 없으면 레코드가 작성됩니다.

이 두 번째 방법에는 다른 문제가 발생할 경우 쿼리 중단을 포함하여 여러 가지 잠재적 약점이 있습니다 (설명서 참조). 따라서 이전에 IGNORE 키워드없이 테스트 한 경우 사용해야합니다.

방법 3 : INSERT… ON DUPLICATE KEY UPDATE 사용 :

세 번째 옵션은 INSERT … ON DUPLICATE KEY UPDATE
구문 을 사용 하는 것이며, UPDATE 부분에서는 0 + 0 계산과 같이 의미없는 (빈) 작업을 수행하지 않습니다 (Geoffray는이 작업을 무시하기 위해 MySQL 최적화 엔진에 id = id 할당을 제안합니다). 이 방법의 장점은 중복 키 이벤트 만 무시하고 다른 오류로 인해 중단된다는 것입니다.

마지막 공지 :이 게시물은 Xaprb에서 영감을 받았습니다. 또한 유연한 SQL 쿼리 작성에 대한 다른 게시물을 참조하는 것이 좋습니다.


답변

해결책:

INSERT INTO `table` (`value1`, `value2`) 
SELECT 'stuff for value1', 'stuff for value2' FROM DUAL 
WHERE NOT EXISTS (SELECT * FROM `table` 
      WHERE `value1`='stuff for value1' AND `value2`='stuff for value2' LIMIT 1) 

설명:

가장 안쪽 쿼리

SELECT * FROM `table` 
      WHERE `value1`='stuff for value1' AND `value2`='stuff for value2' LIMIT 1

애즈 사용 WHERE NOT EXISTS데이터를 삽입하여 이미 행이 존재한다면 -condition 검출한다. 이러한 종류의 행이 발견되면 쿼리가 중지 될 수 있으므로 LIMIT 1(마이크로 최적화, 생략 될 수 있음)

중간 쿼리

SELECT 'stuff for value1', 'stuff for value2' FROM DUAL

삽입 할 값을 나타냅니다. DUAL모든 Oracle 데이터베이스에 기본적으로 존재하는 특수한 행, 하나의 열 테이블을 나타냅니다 ( https://en.wikipedia.org/wiki/DUAL_table 참조 ). MySQL-Server 버전 5.7.26에서 생략 할 때 유효한 쿼리가 FROM DUAL있지만 5.5.60과 같은 이전 버전에는 FROM정보 가 필요한 것 같습니다 . WHERE NOT EXISTS가장 안쪽 쿼리가 일치하는 데이터를 찾은 경우 중간 쿼리 를 사용 하여 빈 결과 집합을 반환합니다.

외부 쿼리

INSERT INTO `table` (`value1`, `value2`) 

중간 쿼리에서 데이터가 반환되면 데이터를 삽입합니다.


답변

중복 키 업데이트 또는 insert ignore 는 MySQL에서 실행 가능한 솔루션 일 수 있습니다.


mysql.com을 기반으로 하는 중복 키 업데이트 업데이트의 예

INSERT INTO table (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=c+1;

UPDATE table SET c=c+1 WHERE a=1;

mysql.com을 기반으로 한 insert ignore 예제

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name [(col_name,...)]
    {VALUES | VALUE} ({expr | DEFAULT},...),(...),...
    [ ON DUPLICATE KEY UPDATE
      col_name=expr
        [, col_name=expr] ... ]

또는:

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name
    SET col_name={expr | DEFAULT}, ...
    [ ON DUPLICATE KEY UPDATE
      col_name=expr
        [, col_name=expr] ... ]

또는:

INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name [(col_name,...)]
    SELECT ...
    [ ON DUPLICATE KEY UPDATE
      col_name=expr
        [, col_name=expr] ... ]


답변

예외가 허용되는 경우 간단한 제한 조건이 작업을 수행해야합니다. 예 :

  • 대리하지 않은 경우 기본 키
  • 열에 대한 고유 제한
  • 다중 열 고유 제한 조건

죄송합니다. 이것은 매우 간단합니다. 당신이 우리와 공유하는 링크에 맞지 않는 것 같습니다. ;-(

그러나 나는 이것이 당신의 필요를 채우는 것처럼 보이기 때문에 결코이 대답을하지 않습니다. (그렇지 않으면 요구 사항 업데이트가 트리거 될 수 있으며, 이는 “좋은 것”이기도합니다).

편집 됨 : 삽입으로 인해 데이터베이스 고유 제한 조건이 중단되면 데이터베이스 레벨에서 드라이버에 의해 릴레이되는 예외가 발생합니다. 실패하면 스크립트가 확실히 중지됩니다. PHP에서 그러한 경우를 해결할 수 있어야합니다 …


답변

다음은 지정된 모든 열 값이 테이블에 존재하지 않는 경우에만 행을 삽입하는 PHP 함수입니다.

  • 열 중 하나가 다르면 행이 추가됩니다.

  • 테이블이 비어 있으면 행이 추가됩니다.

  • 지정된 모든 열에 지정된 값이있는 행이 있으면 행이 추가되지 않습니다.

    function insert_unique($table, $vars)
    {
      if (count($vars)) {
        $table = mysql_real_escape_string($table);
        $vars = array_map('mysql_real_escape_string', $vars);
    
        $req = "INSERT INTO `$table` (`". join('`, `', array_keys($vars)) ."`) ";
        $req .= "SELECT '". join("', '", $vars) ."' FROM DUAL ";
        $req .= "WHERE NOT EXISTS (SELECT 1 FROM `$table` WHERE ";
    
        foreach ($vars AS $col => $val)
          $req .= "`$col`='$val' AND ";
    
        $req = substr($req, 0, -5) . ") LIMIT 1";
    
        $res = mysql_query($req) OR die();
        return mysql_insert_id();
      }
    
      return False;
    }

사용법 예 :

<?php
insert_unique('mytable', array(
  'mycolumn1' => 'myvalue1',
  'mycolumn2' => 'myvalue2',
  'mycolumn3' => 'myvalue3'
  )
);
?>


답변

REPLACE INTO `transcripts`
SET `ensembl_transcript_id` = 'ENSORGT00000000001',
`transcript_chrom_start` = 12345,
`transcript_chrom_end` = 12678;

레코드가 있으면 덮어 씁니다. 아직 존재하지 않으면 작성됩니다.


답변

다음을 시도하십시오 :

IF (SELECT COUNT(*) FROM beta WHERE name = 'John' > 0)
  UPDATE alfa SET c1=(SELECT id FROM beta WHERE name = 'John')
ELSE
BEGIN
  INSERT INTO beta (name) VALUES ('John')
  INSERT INTO alfa (c1) VALUES (LAST_INSERT_ID())
END