programing

중복을 피하기 위해 값이 이미 존재하는지 확인하는 방법은 무엇입니까?

codeshow 2023. 10. 14. 10:45
반응형

중복을 피하기 위해 값이 이미 존재하는지 확인하는 방법은 무엇입니까?

URL 표가 있는데 중복되는 URL은 원하지 않습니다.PHP/MySQL을 사용하여 주어진 URL이 테이블에 이미 있는지 확인하려면 어떻게 해야 합니까?

중복을 원하지 않는 경우 다음을 수행할 수 있습니다.

여러 사용자가 DB에 데이터를 삽입할 수 있는 경우 @Jeremy Ruten이 제안하는 방법으로 오류가 발생할 수 있습니다. 확인을 수행한 후 유사한 데이터를 테이블에 삽입할 수 있습니다.

처음 질문에 답하려면 중복 여부를 확인하는 가장 쉬운 방법은 추가하려는 내용에 대해 SQL 쿼리를 실행하는 것입니다!

를 들어 해야 합니다.http://www.example.com/n에서links 당신의 은 .

SELECT * FROM links WHERE url = 'http://www.example.com/';

당신의 PHP 코드는 다음과 같습니다.

$conn = mysql_connect('localhost', 'username', 'password');
if (!$conn)
{
    die('Could not connect to database');
}
if(!mysql_select_db('mydb', $conn))
{
    die('Could not select database mydb');
}

$result = mysql_query("SELECT * FROM links WHERE url = 'http://www.example.com/'", $conn);

if (!$result)
{
    die('There was a problem executing the query');
}

$number_of_rows = mysql_num_rows($result);

if ($number_of_rows > 0)
{
    die('This URL already exists in the database');
}

데이터베이스에 대한 모든 연결을 포함하여 여기에 긴 손으로 작성했습니다.새 하기 보다는 해야 합니다(다()).$connmysql_query명령을 합니다에 을 제거합니다.mysql_connect그리고.mysql_select_db)

물론, PDO나 ORM을 사용하는 등 데이터베이스에 연결하는 다른 방법도 있습니다. 따라서 이미 이러한 방법을 사용하고 있다면 이 답변은 관련이 없을 수 있습니다(여기서는 이와 관련된 답변을 제공하는 것이 범위를 조금 벗어난 것 같습니다!).

그러나 MySQL은 이러한 일이 발생하지 않도록 여러 가지 방법을 제공합니다.

먼저 필드를 "고유"로 표시할 수 있습니다.

내 사이트에서 링크된 모든 URL과 마지막으로 방문한 URL을 저장할 테이블이 있다고 가정해 보겠습니다.

제 정의는 이렇게 보일 수도 있습니다.

CREATE TABLE links
(
    url VARCHAR(255) NOT NULL,
    last_visited TIMESTAMP
)

이를 통해 위와 유사한 PHP 코드를 작성하지 않는 한, 동일한 URL을 반복적으로 추가할 수 있습니다.

하지만, 제 정의는 다음과 같습니다.

CREATE TABLE links
(
  url VARCHAR(255)  NOT NULL,
  last_visited TIMESTAMP,
  PRIMARY KEY (url)
)

그러면 동일한 값을 두 번 삽입하려고 하면 mysql에서 오류가 발생합니다.

PHP의 예는 다음과 같습니다.

$result = mysql_query("INSERT INTO links (url, last_visited) VALUES ('http://www.example.com/', NOW()", $conn);

if (!$result)
{
    die('Could not Insert Row 1');
}

$result2 = mysql_query("INSERT INTO links (url, last_visited) VALUES ('http://www.example.com/', NOW()", $conn);

if (!$result2)
{
    die('Could not Insert Row 2');
}

첫 가 하면 와 것을 될Could not Insert Row 2그, 에서는, 에서는,Could not Insert Row 1.

이는 MySQL이 url이 테이블의 Primary Key라는 것을 알고 있기 때문입니다.기본 키는 해당 행에 대한 고유 식별자입니다.대부분 행의 고유 식별자를 숫자로 설정하는 것이 유용합니다.이것은 MySQL이 텍스트를 찾는 것보다 숫자를 찾는 것이 더 빠르기 때문입니다.MySQL 내에서 키(특히 Primary Keys)는 두 테이블 간의 관계를 정의하는 데 사용됩니다.예를 들어, 사용자를 위한 테이블이 있다면 다음과 같이 정의할 수 있습니다.

CREATE TABLE users (
  username VARCHAR(255)  NOT NULL,
  password VARCHAR(40) NOT NULL,
  PRIMARY KEY (username)
)

그러나 사용자가 작성한 게시물에 대한 정보를 저장하고자 할 때 해당 게시물의 사용자 이름을 저장하여 해당 게시물이 해당 사용자의 것임을 식별해야 합니다.

MySQL이 문자열보다 숫자를 찾는 속도가 빠르다는 것을 이미 언급했습니다. 따라서 필요 없을 때 문자열을 찾는 데 시간을 소비하게 될 것입니다.

이를 해결하기 위해 user_id라는 열을 추가하여 기본 키로 만들 수 있습니다. (따라서 게시물을 기준으로 사용자 기록을 조회할 때 더 빨리 찾을 수 있습니다.)

CREATE TABLE users (
  user_id INT(10)  NOT NULL AUTO_INCREMENT,
  username VARCHAR(255)  NOT NULL,
  password VARCHAR(40)  NOT NULL,
  PRIMARY KEY (`user_id`)
)

여기에 AUTO_INCREMENT라는 새로운 것도 추가했습니다.이것은 기본적으로 우리가 그 분야를 스스로 돌볼 수 있게 해줍니다.새로운 행을 삽입할 때마다 이전 번호에 1을 추가하여 저장하기 때문에 번호 지정에 대한 걱정이 없고, 그냥 이렇게 할 수 있습니다.

위의 표를 가지고 우리는 다음과 같은 일을 할 수 있습니다.

INSERT INTO users (username, password) VALUES('Mez', 'd3571ce95af4dc281f142add33384abc5e574671');

그리고 나서.

INSERT INTO users (username, password) VALUES('User', '988881adc9fc3655077dc2d4d757d480b5ea0e11');

데이터베이스에서 레코드를 선택하면 다음을 얻을 수 있습니다.

mysql> SELECT * FROM users;
+---------+----------+------------------------------------------+
| user_id | username | password                                 |
+---------+----------+------------------------------------------+
|       1 | Mez      | d3571ce95af4dc281f142add33384abc5e574671 |
|       2 | User     | 988881adc9fc3655077dc2d4d757d480b5ea0e11 |
+---------+----------+------------------------------------------+
2 rows in set (0.00 sec)

그러나 여기에 문제가 있습니다. 같은 사용자 이름을 가진 다른 사용자를 추가할 수 있습니다!분명히, 이것은 우리가 하고 싶지 않은 일입니다!

mysql> SELECT * FROM users;
+---------+----------+------------------------------------------+
| user_id | username | password                                 |
+---------+----------+------------------------------------------+
|       1 | Mez      | d3571ce95af4dc281f142add33384abc5e574671 |
|       2 | User     | 988881adc9fc3655077dc2d4d757d480b5ea0e11 |
|       3 | Mez      | d3571ce95af4dc281f142add33384abc5e574671 |
+---------+----------+------------------------------------------+
3 rows in set (0.00 sec)

테이블 정의를 변경해 보겠습니다!

CREATE TABLE users (
  user_id INT(10)  NOT NULL AUTO_INCREMENT,
  username VARCHAR(255)  NOT NULL,
  password VARCHAR(40)  NOT NULL,
  PRIMARY KEY (user_id),
  UNIQUE KEY (username)
)

이제 같은 사용자를 두 번 삽입하려고 할 때 어떤 일이 일어나는지 알아보겠습니다.

mysql> INSERT INTO users (username, password) VALUES('Mez', 'd3571ce95af4dc281f142add33384abc5e574671');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO users (username, password) VALUES('Mez', 'd3571ce95af4dc281f142add33384abc5e574671');
ERROR 1062 (23000): Duplicate entry 'Mez' for key 'username'

허자!!사용자 이름을 두 번째로 삽입하려고 하면 오류가 발생합니다.위와 같은 것을 사용하면 PHP에서 이것을 감지할 수 있습니다.

이제 링크 테이블로 돌아가서 새로운 정의를 사용해 보겠습니다.

CREATE TABLE links
(
    link_id INT(10)  NOT NULL AUTO_INCREMENT,
    url VARCHAR(255)  NOT NULL,
    last_visited TIMESTAMP,
    PRIMARY KEY (link_id),
    UNIQUE KEY (url)
)

데이터베이스에 "http://www.example.com "을 삽입해 보겠습니다.

INSERT INTO links (url, last_visited) VALUES ('http://www.example.com/', NOW());

다시 삽입을 시도하면..

ERROR 1062 (23000): Duplicate entry 'http://www.example.com/' for key 'url'

그러나 마지막으로 방문한 시간을 업데이트하려면 어떻게 됩니까?

음, PHP로 복잡한 작업을 할 수 있습니다.

$result = mysql_query("SELECT * FROM links WHERE url = 'http://www.example.com/'", $conn);

if (!$result)
{
    die('There was a problem executing the query');
}

$number_of_rows = mysql_num_rows($result);

if ($number_of_rows > 0)
{
    $result = mysql_query("UPDATE links SET last_visited = NOW() WHERE url = 'http://www.example.com/'", $conn);

    if (!$result)
    {
        die('There was a problem updating the links table');
    }
}

또는 데이터베이스에서 행의 ID를 잡고 이를 사용하여 업데이트할 수도 있습니다.

$result =mysql_query("SELECT * FROM links url = 'http://www.example.com/' ', $conn);

if (!$result)
{
    die('There was a problem executing the query');
}

$number_of_rows = mysql_num_rows($result);

if ($number_of_rows > 0)
{
    $row = mysql_fetch_assoc($result);

    $result = mysql_query('UPDATE links SET last_visited = NOW() WHERE link_id = ' . intval($row['link_id'], $conn);

    if (!$result)
    {
        die('There was a problem updating the links table');
    }
}

에는 MySQL 에는라는 .REPLACE INTO

어떻게 하는지 한 번 볼까요.

mysql> SELECT * FROM links;
+---------+-------------------------+---------------------+
| link_id | url                     | last_visited        |
+---------+-------------------------+---------------------+
|       1 | http://www.example.com/ | 2011-08-19 23:48:03 |
+---------+-------------------------+---------------------+
1 row in set (0.00 sec)

mysql> INSERT INTO links (url, last_visited) VALUES ('http://www.example.com/', NOW());
ERROR 1062 (23000): Duplicate entry 'http://www.example.com/' for key 'url'
mysql> REPLACE INTO links (url, last_visited) VALUES ('http://www.example.com/', NOW());
Query OK, 2 rows affected (0.00 sec)

mysql> SELECT * FROM links;
+---------+-------------------------+---------------------+
| link_id | url                     | last_visited        |
+---------+-------------------------+---------------------+
|       2 | http://www.example.com/ | 2011-08-19 23:55:55 |
+---------+-------------------------+---------------------+
1 row in set (0.00 sec)

입니다를 할 때 .REPLACE INTO _!

이는 MySQL에서 행을 바꾸려는 것을 감지하기 때문입니다.url을 고유하게 설정했기 때문에 원하는 행을 알 수 있습니다.MySQL은 고유해야 할 비트(이 경우 url)를 전달하고 해당 행에 대한 다른 값을 업데이트함으로써 대체할 행을 결정합니다.link_id도 업데이트되었는데, 조금 의외입니다! (사실, 저는 이런 일이 일어나는 것을 보고 나서야 이런 일이 일어날 줄 알았습니다.

? URL 요를 하면 요?REPLACE INTO일치하는 고유 행을 찾을 수 없으면 새 행을 기꺼이 삽입합니다!

mysql> REPLACE INTO links (url, last_visited) VALUES ('http://www.stackoverflow.com/', NOW());
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM links;
+---------+-------------------------------+---------------------+
| link_id | url                           | last_visited        |
+---------+-------------------------------+---------------------+
|       2 | http://www.example.com/       | 2011-08-20 00:00:07 |
|       3 | http://www.stackoverflow.com/ | 2011-08-20 00:01:22 |
+---------+-------------------------------+---------------------+
2 rows in set (0.00 sec)

이것이 여러분의 질문에 답하고 MySQL이 어떻게 작동하는지에 대한 정보를 조금 더 제공하기를 바랍니다!

정확히 동일한 문자열인 URL에 대해서만 관심이 있습니까?만약 그렇다면 다른 대답에는 많은 좋은 조언이 있습니다.아니면 시성에 대해서도 걱정해야 합니까?

예를 들어 http://google.com 과 http://go% 4fgle.com 은 완전히 동일한 URL이지만 데이터베이스 전용 기법에서는 중복으로 허용됩니다.이 문제가 발생할 경우 해결할 URL과 문자 탈출 시퀀스를 전처리해야 합니다.

URL이 어디에서 나오는지에 따라 매개 변수 및 응용 프로그램에서 중요한지 여부에 대해서도 고민해야 합니다.

먼저 데이터베이스를 준비합니다.

  • 도메인 이름은 대소문자를 구분하지 않지만 URL의 나머지 부분은 대소문자를 구분하지 않는 것으로 가정해야 합니다. (모든 웹 서버가 대소문자를 URL에서 존중하는 것은 아니지만 대부분의 서버에서 대소문자를 구분하고 있으며, 쉽게 확인할 수 없습니다.)
  • 도메인 이름 이상을 저장해야 하는 경우 대/소문자를 구분한 대조를 사용합니다.
  • URL을 도메인 이름에 대한 열과 리소스 로케이터에 대한 열 두 개에 저장하기로 결정한 경우 도메인 이름에는 대소문자 구분 집합을 사용하고 리소스 로케이터에는 대소문자 구분 집합을 사용하는 것이 좋습니다.제가 당신이라면 두 가지 방법(한 열의 URL vs.URL을 두 열에 포함) 입력합니다.
  • URL 열에 UNIQUE 제약 조건을 넣습니다. 열 다로 UNIQUE (url, resource_locator).
  • CHECK() 제약 조건을 사용하여 인코딩된 URL을 데이터베이스 밖으로 유지합니다.이 CHECK() 제약 조건은 대량 복사 또는 SQL 셸을 통해 잘못된 데이터가 들어오는 것을 방지하는 데 필수적입니다.

둘째, URL을 준비합니다.

  • 도메인 이름은 대소문자를 구분하지 않습니다.전체 URL을 한 열에 저장하는 경우 모든 URL에서 도메인 이름을 소문자로 바꿉니다.그러나 일부 언어에는 소문자가 없는 대문자가 있습니다.
  • 뒤에 오는 글자들을 다듬는 것을 생각해 보세요.예를 들어 amazon.com 의 이 두 URL은 동일한 제품을 가리킵니다.첫 번째 버전이 아니라 두 번째 버전을 저장하고 싶을 것입니다.

    http://www.amazon.com/Systemantics-Systems-Work-Especially-They/dp/070450331X/ref=sr_1_1?ie=UTF8&qid=1313583998&sr=8-1

    http://www.amazon.com/Systemantics-Systems-Work-Especially-They/dp/070450331X

  • 인코딩된 URL을 디코딩합니다. (php의 urdecode() 함수 참조).해당 페이지의 설명에 나와 있는 단점을 주의 깊게 기록합니다.)개인적으로, 저는 클라이언트 코드보다는 데이터베이스에서 이런 종류의 변환을 처리하고 싶습니다.테이블과 보기에 대한 권한을 취소하고 저장 프로시저를 통해서만 삽입 및 업데이트를 허용하는 것이 포함됩니다. 저장 프로시저는 URL을 표준 형식으로 만드는 모든 문자열 작업을 처리합니다.하지만 그런 시도를 할 때는 성능을 잘 지켜보세요.CHECK() 제약 조건(위 참조)이 안전망입니다.

셋째, URL만 삽입하는 경우 먼저 URL 존재 여부를 테스트하지 마십시오.대신 값이 이미 존재할 경우 발생하는 오류를 삽입하고 트랩을 시도합니다.테스트 및 삽입은 새 URL마다 두 번씩 데이터베이스에 도달하며 삽입 및 트랩은 한 번만 데이터베이스에 도달합니다.삽입 및 트랩은 삽입 및 무시 오류와 동일하지 않습니다.특정 오류가 하나만 있으면 고유한 제약 조건을 위반한 것이고, 다른 오류는 다른 문제가 있다는 것을 의미합니다.

한편, 같은 행에 있는 다른 데이터와 함께 URL을 삽입하는 경우 중복 URL을 처리할지 여부를 미리 결정해야 합니다.

REFACE를 사용하면 중복된 키 오류를 트래핑할 필요가 없지만, 외부 키 참조가 있는 경우 유감스럽게도 부작용이 발생할 수 있습니다.

고유성을 보장하려면 고유한 제약 조건을 추가해야 합니다.테이블 이름이 "urls"이고 열 이름이 "url"이라고 가정하면 다음과 같은 altertable 명령을 사용하여 고유한 제약 조건을 추가할 수 있습니다.

alter table urls add constraint unique_url unique (url);

테이블에 이미 중복 URL이 있는 경우(MySQL을 실제로 알고 있는 사용자) 변경 테이블이 실패할 수 있습니다.

단순한 SQL 솔루션에는 고유한 필드가 필요하지만 논리 솔루션에는 그렇지 않습니다.

중복이 없도록 URL을 정상화해야 합니다.strtlower(), urdecode() 또는 rawurdecode()와 같은 PHP의 함수입니다.

가정:테이블 이름은 'websites', URL의 열 이름은 'url', URL과 연결할 임의의 데이터는 'data' 열에 있습니다.

논리 솔루션

SELECT COUNT(*) AS UrlResults FROM websites WHERE url='http://www.domain.com'

이전 쿼리를 SQL 또는 PHP의 if 문으로 테스트하여 INSERT 문을 계속 진행하기 전에 0인지 확인합니다.

간단한 SQL 문

시나리오 1: 귀하의 DB는 선착순 서비스 테이블이며 향후 중복 입력을 원하지 않습니다.

ALTER TABLE websites ADD UNIQUE (url)

이렇게 하면 해당 열에 URL 값이 이미 있는 경우에는 데이터베이스에 항목을 입력할 수 없습니다.

시나리오 2: 각 url에 대한 최신 정보를 가장 원하고 내용을 복제하지 않을 것입니다.이 시나리오에는 두 가지 해결책이 있습니다.(이러한 솔루션에는 'url'도 고유해야 하므로 시나리오 1의 솔루션도 수행해야 합니다.)

REPLACE INTO websites (url, data) VALUES ('http://www.domain.com', 'random data')

행이 존재할 경우 DELETE 동작이 트리거되고 모든 경우 INSERT가 이어지므로 ON DELETE 선언에 주의해야 합니다.

INSERT INTO websites (url, data) VALUES ('http://www.domain.com', 'random data')
ON DUPLICATE KEY UPDATE data='random data'

행이 있으면 UPDATE 작업을, 없으면 INSERT 작업을 트리거합니다.

이 문제에 대한 해결책을 고려할 때, 먼저 프로젝트에 대해 "중복 URL"이 무엇을 의미하는지 정의해야 합니다.이렇게 하면 URL을 데이터베이스에 추가하기 전에 표준화하는 방법이 결정됩니다.

적어도 두 가지 정의가 있습니다.

  1. 두 개의 URL이 동일한 리소스를 나타내는 경우 해당 컨텐츠를 생성하는 해당 웹 서비스에 대해 아무것도 모르는 경우 중복으로 간주됩니다.고려해야 할 사항은 다음과 같습니다.
    • URL의 스킴 및 도메인 이름 부분은 대소문자를 구분하지 않으므로 HTTP://WWW.스택 오버플로.COM/은(는) http://www.stackoverflow.com/ 과 동일합니다.
    • URL 중 하나가 포트를 지정하지만 이 포트가 스킴의 기존 포트이며 동일한 경우(http://www.stackoverflow.com/ 및 http://www.stackoverflow.com:80/) ) 동일합니다.
    • 쿼리 문자열의 매개 변수가 단순 재정렬이고 매개 변수 이름이 모두 다를 경우 http://authority/?a=test&b=testhttp:///?b=test&a=test.http://authority/?a%5B%5D=test1&a%5B%5D=test2http://authority/?a%5B%5D=test1과 동일하지 않습니다.
    • 스킴이 HTTP 또는 HTTPS인 경우 URL의 이 부분이 웹 서버로 전송되지 않으므로 URL의 해시 부분을 제거할 수 있습니다.
    • 단축 IPv6 주소를 확장할 수 있습니다.
    • 누락된 경우에만 기관에 후행 전달 슬래시를 추가합니다.
    • 유니코드 표준화는 참조된 리소스를 변경합니다. 예를 들어 http://google.com/ ?q=%C3%84(%C3%84UTF-8)에서 'ä'를 나타냄)이 http://google.com/ ?q=A%CC%88(%CC%88는 U+0308, 결합 DIAERESIS) 를 나타냅니다.
    • HTTP HTTPS 이'www.가 ' 의 URL 의' 두 한 을 간단히 할 수 .HostHTTP 헤더와 일부 웹 서버는 가상 호스트를 사용하여 이 헤더를 기반으로 다른 내용을 다시 보냅니다.일반적으로 도메인 이름이 동일한 IP 주소로 확인되더라도 참조되는 리소스가 동일하다고 결론 내릴 수는 없습니다.
  2. 기본 URL 표준화(예: 스킴 및 도메인 이름 소문자, 기본 포트 제공, 파라미터 이름별 안정 정렬 쿼리 파라미터, HTTP 및 HTTPS의 경우 해시 부분 제거, ...)를 적용하고 웹 서비스에 대한 지식을 고려합니다.아마도 모든 웹 서비스가 유니코드 입력을 표준화할 수 있을 정도로 충분히 똑똑하다고 가정할 것입니다(위키피디아는 예를 들어). 그래서 유니코드 정규화 양식 표준 구성(NFC)을 적용할 수 있습니다.당신은 옷을 벗길겁니다www.' 모든 Stack Overflow URL에서.PHP로 포팅된 PostRank의 postrank-uri 코드를 사용하여 불필요한 모든 종류의 URL을 제거할 수 있습니다.&utm_source=...).

정의 1은 안정적인 솔루션으로 이어집니다(즉, 수행할 수 있는 더 이상의 표준화가 없으며 URL의 표준화는 변경되지 않습니다).인간이 URL 표준화의 정의로 생각하는 정의 2는 시간에 따라 다른 결과를 얻을 수 있는 표준화 루틴으로 이어집니다.

어떤 정의를 선택하든 스킴, 로그인, 호스트, 포트 및 경로 부분에 대해 별도의 열을 사용하는 것이 좋습니다.이렇게 하면 인덱스를 지능적으로 사용할 수 있습니다.스키마 및 호스트 열은 문자 조합을 사용할 수 있지만(MySQL에서는 모든 문자 조합이 대소문자를 구분하지 않음), 로그인 및 경로 열은 이진 대소문자를 구분하지 않는 조합을 사용해야 합니다.또한 정의 2를 사용하는 경우 특정 정규화 규칙이 때때로 추가되거나 제거될 수 있으므로 원래 스킴, 권한 및 경로 부분을 보존해야 합니다.

EDIT: 테이블 정의의 예시는 다음과 같습니다.

CREATE TABLE `urls1` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
    `scheme` VARCHAR(20) NOT NULL,
    `canonical_login` VARCHAR(100) DEFAULT NULL COLLATE 'utf8mb4_bin',
    `canonical_host` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_unicode_ci', /* the "ci" stands for case-insensitive. Also, we want 'utf8mb4_unicode_ci'
rather than 'utf8mb4_general_ci' because 'utf8mb4_general_ci' treats accented characters as equivalent. */
    `port` INT UNSIGNED,
    `canonical_path` VARCHAR(4096) NOT NULL COLLATE 'utf8mb4_bin',

    PRIMARY KEY (`id`),
    INDEX (`canonical_host`(10), `scheme`)
) ENGINE = 'InnoDB';


CREATE TABLE `urls2` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
    `canonical_scheme` VARCHAR(20) NOT NULL,
    `canonical_login` VARCHAR(100) DEFAULT NULL COLLATE 'utf8mb4_bin',
    `canonical_host` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_unicode_ci',
    `port` INT UNSIGNED,
    `canonical_path` VARCHAR(4096) NOT NULL COLLATE 'utf8mb4_bin',

    `orig_scheme` VARCHAR(20) NOT NULL, 
    `orig_login` VARCHAR(100) DEFAULT NULL COLLATE 'utf8mb4_bin',
    `orig_host` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_unicode_ci',
    `orig_path` VARCHAR(4096) NOT NULL COLLATE 'utf8mb4_bin',

    PRIMARY KEY (`id`),
    INDEX (`canonical_host`(10), `canonical_scheme`),
    INDEX (`orig_host`(10), `orig_scheme`)
) ENGINE = 'InnoDB';

표 'urls1'은 정의 1에 따라 표준 URL을 저장하기 위한 것입니다.표 'urls2'는 정의 2에 따라 표준 URL을 저장하기 위한 것입니다.

도 할 수 .UNIQUEMySQL 이 InnoDB 키의 길이를 767 바이트로 제한하기 때문에 튜플에 대한 제약('scheme'/'canonical_scheme', 'canonical_loginin', 'canonical_host', 'port', 'canonical_path').

MySQL에 대한 구문은 모르지만, 표를 쿼리하여 URL이 지정된 레코드가 존재하는지, 존재하는지 확인하는 IF 문으로 INSERT를 랩핑하기만 하면 됩니다. 새 레코드를 삽입하지 마십시오.

MSSQL인 경우 다음을 수행할 수 있습니다.

IF NOT EXISTS (SELECT 1 FROM YOURTABLE WHERE URL = 'URL')
INSERT INTO YOURTABLE (...) VALUES (...)

테이블에 URL을 삽입하고 싶지만 이미 존재하지 않는 URL만 있으면 열에 고유한 제약 조건을 추가하고 INSERT 쿼리에 오류가 발생하지 않도록 무시를 추가할 수 있습니다.

: 합니다.urlsSET URL = ' 삽입할 url'

첫 번째 일부터.테이블을 작성하지 않았거나 테이블을 작성했지만 데이터가 없는 경우 고유 제약 조건 또는 고유 색인을 추가해야 합니다.인덱스 또는 제약 조건 중 하나를 선택하는 것에 대한 자세한 정보는 게시물의 끝에 나와 있습니다.그러나 이 둘은 동일한 작업을 수행하여 열에 고유한 값만 포함하도록 강제합니다.

이 열에 고유 인덱스가 있는 테이블을 만들려면 다음을 사용할 수 있습니다.

CREATE TABLE MyURLTable(
ID INTEGER NOT NULL AUTO_INCREMENT
,URL VARCHAR(512)
,PRIMARY KEY(ID)
,UNIQUE INDEX IDX_URL(URL)
);

해당 테이블에 인덱스가 없고 고유한 제약 조건만 원하는 경우 다음을 사용할 수 있습니다.

CREATE TABLE MyURLTable(
ID INTEGER NOT NULL AUTO_INCREMENT
,URL VARCHAR(512)
,PRIMARY KEY(ID)
,CONSTRAINT UNIQUE UNIQUE_URL(URL)
);

이제 테이블이 이미 있는데 그 안에 데이터가 없다면 다음 코드 중 하나를 사용하여 테이블에 인덱스 또는 제약 조건을 추가할 수 있습니다.

ALTER TABLE MyURLTable
ADD UNIQUE INDEX IDX_URL(URL);

ALTER TABLE MyURLTable
ADD CONSTRAINT UNIQUE UNIQUE_URL(URL);

데이터가 포함된 표가 이미 있을 수도 있습니다.이 경우 이미 중복된 데이터가 있을 수 있습니다.위에 표시된 제약 조건 또는 인덱스를 만들어 볼 수 있으며, 이미 중복된 데이터가 있으면 실패합니다.중복 데이터가 없는 경우에는 중복 데이터를 제거해야 합니다.다음 쿼리를 사용하여 중복된 URL을 볼 수 있습니다.

SELECT URL,COUNT(*),MIN(ID) 
FROM MyURLTable
GROUP BY URL
HAVING COUNT(*) > 1;

중복된 행을 삭제하고 하나를 유지하려면 다음을 수행합니다.

DELETE RemoveRecords
FROM MyURLTable As RemoveRecords
LEFT JOIN 
(
SELECT MIN(ID) AS ID
FROM MyURLTable
GROUP BY URL
HAVING COUNT(*) > 1
UNION
SELECT ID
FROM MyURLTable
GROUP BY URL
HAVING COUNT(*) = 1
) AS KeepRecords
ON RemoveRecords.ID = KeepRecords.ID
WHERE KeepRecords.ID IS NULL;

이제 모든 레코드를 삭제했으므로 인덱스 또는 제약 조건을 생성할 수 있습니다.이제 데이터베이스에 값을 삽입하려면 다음과 같은 방법을 사용해야 합니다.

INSERT IGNORE INTO MyURLTable(URL)
VALUES('http://www.example.com');

그러면 삽입이 시도되고 중복되는 것이 발견되면 아무 일도 일어나지 않습니다.자, 다른 칼럼이 있다고 치자, 이런 작업을 할 수 있습니다.

INSERT INTO MyURLTable(URL,Visits) 
VALUES('http://www.example.com',1)
ON DUPLICATE KEY UPDATE Visits=Visits+1;

그러면 값을 삽입하려고 시도하고 URL을 찾으면 방문 카운터를 증가시켜 레코드를 업데이트합니다.물론 당신은 언제든지 평범한 오래된 삽입을 할 수 있고, 당신의 PHP 코드에서 발생한 오류를 처리할 수 있습니다.제약 조건 또는 인덱스를 사용해야 하는지 여부는 여러 요인에 따라 달라집니다.인덱스를 사용하면 검색 속도가 빨라지기 때문에 테이블이 커질수록 성능이 향상되지만 인덱스를 저장하면 추가 공간을 차지합니다.인덱스는 인덱스를 업데이트해야 하기 때문에 일반적으로 삽입 및 업데이트 시간도 더 오래 걸립니다.그러나 값은 어느 쪽이든 조회해야 하므로 이 경우 고유성을 적용하기 위해 인덱스만 갖는 것이 더 빠를 수 있습니다.성능과 관련된 모든 것에 대해서는 옵션을 모두 사용해 보고 결과를 프로파일링하여 어떤 것이 자신의 상황에 가장 적합한지 확인해 보는 것이 답입니다.

예 또는 아니오로만 대답하려면 이 구문이 최상의 성능을 제공해야 합니다.

듀얼에서 if(exists = 'http://asdf.com '인 URL에서 url 선택, 1, 0)를 선택합니다.

중복되는 항목이 없는지 확인한 다음 url 필드에 고유한 인덱스를 추가하면 url이 존재하는지 명시적으로 확인할 필요가 없습니다. 이렇게 하면 url이 존재하는지 정상적으로 삽입하면 삽입이 실패하고 중복 키 오류가 발생합니다.

답은 중복된 필드가 있는 레코드를 언제 입력하려고 하는지 여부에 따라 달라집니다.상관없다면 "INSERT..."를 사용합니다.ON DUFFIC KEY" 구문을 사용하면 중복을 만들지 않고 조용히 시도할 수 있습니다.

반면에 언제 이러한 이벤트가 발생하는지 알고 이벤트를 방지하려면 고유한 키 제약 조건을 사용해야 합니다. 그러면 삽입/업데이트 시도가 의미 있는 오류와 함께 실패하게 됩니다.

$url = "http://www.scroogle.com";

$query  = "SELECT `id` FROM `urls` WHERE  `url` = '$url' ";
$resultdb = mysql_query($query) or die(mysql_error());   
list($idtemp) = mysql_fetch_array($resultdb) ;

if(empty($idtemp)) // if $idtemp is empty the url doesn't exist and we go ahead and insert it into the db.
{ 
   mysql_query("INSERT INTO urls (`url` ) VALUES('$url') ") or die (mysql_error());
}else{
   //do something else if the url already exists in the DB
}

열을 다음과 같이 만듭니다.primary key

자가 결합을 사용하여 위치를 찾고 제거할 수 있습니다.테이블에 URL과 PK가 있습니다(그렇지 않으면 중복되는 것이 허용되지 않으므로 PK가 URL이 아님을 알고 있습니다).

SELECT
    *
FROM
    yourTable a
JOIN
    yourTable b -- Join the same table
        ON b.[URL] = a.[URL] -- where the URL's match
        AND b.[PK] <> b.[PK] -- but the PK's are different

이렇게 하면 URL이 중복된 모든 행이 반환됩니다.

하지만, 당신은 복제품만 선택하고 원본은 제외하고 싶었다고 하세요.원본을 구성하는 것이 무엇인지 결정해야 합니다.이 답변의 목적을 위해 가장 낮은 PK를 "original"이라고 가정합니다.

위 쿼리에 다음 절만 추가하면 됩니다.

WHERE
    a.[PK] NOT IN (
        SELECT 
            TOP 1 c.[PK] -- Only grabbing the original!
        FROM
            yourTable c
        WHERE
            c.[URL] = a.[URL] -- has the same URL
        ORDER BY
            c.[PK] ASC) -- sort it by whatever your criterion is for "original"

이제 원본이 아닌 모든 중복 행 집합이 있습니다.다를 할 수 .DELETE아니면 이 결과 세트에서 당신이 원하는 것이 무엇이든.

mySQ를 접근 일 수 .L이 항상 처리하지 않기 때문에 이 접근 방식은 비효율적일 수 있습니다.IN하지만 OP로부터 이것이 항상 견제가 아니라 테이블 위에 있는 일종의 "정리"라는 것을 이해합니다.

을 원하시는 INSERT에 관계없이 다와 할 수 .

SELECT 
    1
WHERE
    EXISTS (SELECT * FROM yourTable WHERE [URL] = 'testValue')

결과가 나오면 DB에 이미 존재하는 값을 한 번이라도 결론 내릴 수 있습니다.

다음 쿼리를 수행할 수 있습니다.

SELECT url FROM urls WHERE url = 'http://asdf.com' LIMIT 1

그런 다음 mysql_num_rows () == 1이 존재하는지 확인합니다.

언급URL : https://stackoverflow.com/questions/61033/how-to-check-if-a-value-already-exists-to-avoid-duplicates

반응형