MySQL හි 'නොපවතී නම් ඇතුල් කරන්නේ' කෙසේද?


863

මම ගොග්ලිං වලින් ආරම්භ කළ අතර, මෙම ලිපිය මුටෙක්ස් වගු ගැන කතා කරන ලිපිය සොයා ගතිමි .

මට ඩොලර් මිලියන 14 ක වාර්තා සහිත මේසයක් තිබේ. මට එකම ආකෘතියෙන් තවත් දත්ත එක් කිරීමට අවශ්‍ය නම්, විමසුම් යුගලයක් භාවිතා නොකර මට ඇතුළු කිරීමට අවශ්‍ය වාර්තාව දැනටමත් නොපවතින බව සහතික කිරීමට ක්‍රමයක් තිබේද (එනම්, පරීක්ෂා කිරීමට එක් විමසුමක් සහ ඇතුළු කිරීමට එකක් නම් ප්‍රති result ල කට්ටලය වේ හිස්)?

uniqueක්ෂේත්‍රයක ඇති බාධකයක් insertඑය දැනටමත් තිබේ නම් එය අසාර්ථක වන බවට සහතික වේද?

එය සමග බව පෙනේ හුදෙක් එය අවහිරතා, මම php හරහා ඇතුලත් කරන්න නිකුත් කරන විට, ස්ක්රිප්ට් croaks.



ස්වයංක්‍රීය_ අගයන් දහනය නොකිරීම පිළිබඳ සාකච්ඡා කිරීම සඳහා stackoverflow.com/questions/44550788/… බලන්න .
රික් ජේම්ස්

Ick රික් ජේම්ස් - එය සිත්ගන්නාසුලු q .. නමුත් එය මෙම q සමඟ කෙලින්ම සම්බන්ධ බව විශ්වාස නැත :)
වොරන්

1
එය විවරණයක සඳහන් කර ඇති අතර අනෙක් ප්‍රශ්නය කියා සිටියේ මෙම ප්‍රශ්නය “නිශ්චිත අනුපිටපතක්” බවයි. ඒ නිසා, අනෙක් අයගේ ප්‍රයෝජනය සඳහා ප්‍රශ්න එකට සම්බන්ධ කිරීම හොඳ අදහසක් බව මට හැඟුණි.
රික් ජේම්ස්

1
ඔහ්, මම කවදාවත් පැති තීරුව දෙස බැලීමට නොසිතමි.
රික් ජේම්ස්

Answers:


828

භාවිත 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 වෙතින් පැහැදිලි කිරීම් සොයාගත හැකිය


ගූගල් වෙබ් කැමරාවට අනුව bogdan.org.ua වෙතින් පළ කරන්න :

2007 ඔක්තෝබර් 18

ආරම්භ කිරීමට: නවතම MySQL අනුව, මාතෘකාව තුළ ඉදිරිපත් කර ඇති සින්ටැක්ස් කළ නොහැක. නමුත් පවතින ක්‍රියාකාරීත්වය භාවිතා කර අපේක්ෂිත දේ ඉටු කර ගැනීම සඳහා ඉතා පහසු ක්‍රම කිහිපයක් තිබේ.

කළ හැකි විසඳුම් 3 ක් ඇත: INSERT IGNORE, REPLACE, හෝ INSERT… DUPLICATE KEY UPDATE භාවිතා කිරීම.

අපට මේසයක් ඇතැයි සිතන්න:

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;

දැන් සිතන්න අපට එන්සෙම්බල් වෙතින් පිටපත් මෙටා-දත්ත ආනයනය කරන ස්වයංක්‍රීය නල මාර්ගයක් ඇති බවත්, විවිධ හේතූන් නිසා ඕනෑම පියවරක දී නල මාර්ගය කැඩී යා හැකි බවත්. මේ අනුව, අප කරුණු දෙකක් සහතික කළ යුතුය:

  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' දැනටමත් දත්ත ගබඩාවේ තිබේ නම්, එය නිහ ly ව මඟ හරිනු ඇත (නොසලකා හරිනු ලැබේ). (වඩාත් නිවැරදිව කිවහොත්, MySQL යොමු අත්පොතෙන් උපුටා දැක්වීමක් මෙහි දැක්වේ: “ඔබ IGNORE යතුරු පදය භාවිතා කරන්නේ නම්, INSERT ප්‍රකාශය ක්‍රියාත්මක කිරීමේදී සිදුවන දෝෂ ඒ වෙනුවට අනතුරු ඇඟවීම් ලෙස සලකනු ලැබේ. හෝ වගුවේ ඇති ප්‍රාථමික කේ අගය අනුපිටපත් යතුරු දෝෂයක් ඇති කර ප්‍රකාශය අහෝසි කර ඇත. ”.) වාර්තාව තවමත් නොපවතී නම්, එය නිර්මාණය වනු ඇත.

මෙම දෙවන ක්‍රමයට විභව දුර්වලතා කිහිපයක් ඇත, වෙනත් ගැටළුවක් ඇති වුවහොත් විමසුම ගබ්සා නොකිරීම ද ඇතුළුව (අත්පොත බලන්න). මේ අනුව IGNORE යතුරුපදය නොමැතිව කලින් පරීක්ෂා කර ඇත්නම් එය භාවිතා කළ යුතුය.

ක්රමය 3: ද්විත්ව කේ යාවත්කාලීන කිරීම සඳහා INSERT භාවිතා කිරීම:

තෙවන විකල්පය වන්නේ INSERT … ON DUPLICATE KEY UPDATE සින්ටැක්ස් භාවිතා කිරීමයි , සහ යාවත්කාලීන කිරීමේ කොටසෙහි 0 + 0 ගණනය කිරීම වැනි අර්ථ විරහිත (හිස්) මෙහෙයුමක් නොකරන්න (මෙම ක්‍රියාව නොසලකා හැරීම සඳහා MySQL ප්‍රශස්තිකරණ එන්ජිම සඳහා id = id පැවරුම සිදු කිරීමට ජෙෆ්රේ යෝජනා කරයි). මෙම ක්‍රමයේ ඇති වාසිය නම් එය අනුපිටපත් ප්‍රධාන සිදුවීම් පමණක් නොසලකා හැරීම සහ වෙනත් දෝෂ මත තවමත් නතර වීමයි.

අවසාන දැනුම්දීමක් ලෙස: මෙම ලිපිය Xaprb විසින් දේවානුභාවයෙන්. නම්‍යශීලී SQL විමසුම් ලිවීම පිළිබඳ ඔහුගේ අනෙක් තනතුරෙන් විමසීමට ද මම උපදෙස් දෙමි.


3
පිටපත වේගවත් කිරීම සඳහා මට එය "ප්‍රමාද" සමඟ ඒකාබද්ධ කළ හැකිද?
වරෙන්

3
ඔව්, ඇතුළත් කිරීම ප්‍රමාද කිරීමෙන් ඔබ වෙනුවෙන් දේවල් වේගවත් විය හැකිය. එය අත්හදා බලන්න
knittl


10
INSERT … ON DUPLICATE KEY UPDATEපේළිය මකා නොදමන බැවින් ඕනෑම auto_incrementතීරු සහ වෙනත් දත්ත සංරක්ෂණය කිරීම වඩා හොඳය .
redolent

16
සෑම කෙනෙකුටම දැනුම් දීමට පමණි. INSERT … ON DUPLICATE KEY UPDATEක්‍රමවේදය භාවිතා කිරීම අසාර්ථක ඇතුළු කිරීම් සමඟ ඕනෑම AUTO_INCREMENT තීරුවක් වැඩි කරයි. බොහෝ විට එය අසාර්ථක නොවූ නමුත් යාවත්කාලීන කරන්න.
not2qubit

232

විසඳුමක්:

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සියලුම ඔරකල් දත්ත සමුදායන්හි පෙරනිමියෙන් ඉදිරිපත් කර ඇති විශේෂ එක් පේළියක්, එක් තීරු වගුවක් ( https://en.wikipedia.org/wiki/DUAL_table බලන්න ). MySQL-Server අනුවාදයක 5.7.26 මග හැරීමේදී මට වලංගු විමසුමක් ලැබුණි FROM DUAL, නමුත් පැරණි අනුවාදයන්ට (5.5.60 වැනි) FROMතොරතුරු අවශ්‍ය බව පෙනේ . WHERE NOT EXISTSඅභ්‍යන්තර විමසුම ගැලපෙන දත්ත සොයාගත හොත් අතරමැදි විමසුම භාවිතා කිරීමෙන් හිස් ප්‍රති result ල කට්ටලයක් ලැබේ.

පිටත විමසුම

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

අතරමැදි විමසුම මඟින් කිසියම් දෙයක් ආපසු ලබා දෙන්නේ නම් දත්ත ඇතුල් කරයි.


4
මෙය භාවිතා කරන්නේ කෙසේද යන්න පිළිබඳ තවත් තොරතුරු ලබා දිය හැකිද?
ඇලෙක්ස් වී

39
වගුවේ අද්විතීය යතුරක් නොමැති නම් මෙම ප්‍රභේදය සුදුසු වේ ( INSERT IGNOREසහ INSERT ON DUPLICATE KEYඅද්විතීය යතුරු අවහිරතා අවශ්‍ය වේ)
රබුඩ්

2
ඔබ "වගුවෙන්" වෙනුවට 2 වන පේළියේ "ද්විත්ව සිට" භාවිතා කරන්නේ නම්, ඔබට "සීමාව 1" වගන්තිය අවශ්‍ය නොවේ.
පොහොසත්

6
දේ නම් stuff for value1හා stuff for value2සමාන ද? මෙය විසි කරයිDuplicate column name
රොබින්

1
උපසිරැසි SELECT 1වෙනුවට මම ද වැඩි කැමැත්තක් SELECT *දක්වමි. දර්ශකයකින් මෙය සෑහීමට පත් වීමට බොහෝ දුරට ඉඩ තිබේ.
ආතත්

61

අනුපිටපත් යතුරු යාවත්කාලීන කිරීමේදී හෝ නොසලකා හැරීම ඇතුළු කිරීම 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 [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] ... ]

24

ව්‍යතිරේකයක් පිළිගත හැකි නම් ඕනෑම සරල බාධකයක් එම කාර්යය කළ යුතුය. උදාහරණ :

  • ප්‍රාථමික යතුර අන්‍යාගමික නොවේ නම්
  • තීරුවක අද්විතීය බාධකය
  • බහු තීරු අද්විතීය අවහිරතා

කණගාටුයි, මෙය රැවටිලිකාර ලෙස සරල බව පෙනේ. ඔබ අප සමඟ බෙදාගන්නා සබැඳියට එය නරක ලෙස පෙනෙන බව මම දනිමි. ;-(

නමුත් මම කිසි විටෙකත් මෙම පිළිතුර ලබා නොදෙන්නේ එය ඔබගේ අවශ්‍යතාවය සපුරාලන බැවිනි. (එසේ නොවේ නම්, එය ඔබගේ අවශ්‍යතා යාවත්කාලීන කිරීම අවුලුවන අතර එය “හොඳ දෙයක්” (ටීඑම්) ද වනු ඇත).

සංස්කරණය කරන ලදි : ඇතුළු කිරීමක් මඟින් දත්ත සමුදායේ අද්විතීය අවහිරතා බිඳ දැමිය හැකි නම්, ව්‍යතිරේකය යනු දත්ත සමුදා මට්ටමින් විසි කිරීමකි. එය නිසැකවම ඔබගේ පිටපත අසාර්ථක වනු ඇත. එම නඩුව විසඳීමට PHP හි හැකි විය යුතුය ...


1
මම ප්‍රශ්නයට පැහැදිලි කිරීමක් එක් කළෙමි - ඔබේ පිළිතුර තවමත් අදාළ වේද?
වරෙන්

2
මම විශ්වාස කරනවා ඒක එහෙම කරයි කියලා. අද්විතීය බාධකයක් වැරදි ඇතුළත් කිරීම් අසමත් වීමට හේතු වේ. සටහන: ඔබේ කේතයේ මෙම අසාර්ථකත්වය සමඟ කටයුතු කිරීමට ඔබට සිදු වේ, නමුත් මෙය තරමක් සම්මත ය.
KLE

1
දැන් මම පිළිගත් විසඳුම සමඟ බැඳී සිටිමි - නමුත් යෙදුම වර්ධනය වන විට INSERT අසමත්වීම් පාලනය කිරීම පිළිබඳව තවදුරටත් සොයා බලනු ඇත
වරෙන්

3
INSERT IGNOREඔබේ ස්ක්‍රිප්ටයට බාධා නොවන පරිදි මූලික වශයෙන් සියලු දෝෂ අනතුරු ඇඟවීම් වලට වෙනස් කරයි. එවිට ඔබට විධානය සමඟ ඕනෑම අනතුරු ඇඟවීමක් නැරඹිය හැකිය SHOW WARNINGS. තවත් වැදගත් සටහනක් : UNIQUE අවහිරතා NULL අගයන් සමඟ ක්‍රියා නොකරයි, එනම්. පේළිය 1 (1, එන්.යූ.එල්.එල්) සහ පේළිය 2 (1, එන්.යූ.එල්.එල්) යන දෙකම ඇතුළත් වේ (ප්‍රාථමික යතුරක් වැනි තවත් බාධකයක් කැඩී නැතිනම්). අවාසනාවන්තයි.
සයිමන් ඊස්ට්

18

මෙන්න 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'
  )
);
?>

5
ඔබට විශාල ඇතුළු කිරීම් ප්‍රමාණයක් තිබේ නම් එය ඉතා මිල අධිකය.
ඊයාඩ් ෆල්ලාටා

ඔබට නිශ්චිත පිරික්සුම් එකතු කිරීමට අවශ්‍ය නම් සත්‍ය, නමුත් කාර්යක්ෂම
චාල්ස් ෆොරස්ට්

1
අවවාදයයි: mysql_* PHP 5.5.0 වන විට දිගුව ඉවත් කර ඇති අතර PHP 7.0.0 වන විට ඉවත් කර ඇත. ඒ වෙනුවට, mysqli හෝ PDO_MySQL දිගුව භාවිතා කළ යුතුය. MySQL API තෝරාගැනීමේදී වැඩිදුර සහාය සඳහා MySQL API දළ විශ්ලේෂණයද බලන්න .
ධර්මන්

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

වාර්තාව තිබේ නම්, එය නැවත ලියනු ලැබේ; එය තවමත් නොපවතී නම්, එය නිර්මාණය වනු ඇත.


11
REPLACEපේළිය මකා දමා යාවත්කාලීන කිරීම වෙනුවට ඇතුළත් කළ හැකිය. අතුරු ආබාධය වන්නේ අවහිරතා වෙනත් වස්තූන් මකා දැමිය හැකි අතර ප්‍රේරක මකා දැමීමයි.
xmedeko

1
MySQL අත්පොතෙන්: "ප්‍රතිස්ථාපනය අර්ථවත් වන්නේ වගුවකට ප්‍රාථමික කේ හෝ අද්විතීය දර්ශකයක් තිබේ නම් පමණි. එසේ නොවුවහොත් එය INSERT ට සමාන වේ, මන්ද නව පේළියක් තවත් අනුපිටපතක් තිබේද යන්න තීරණය කිරීමට දර්ශකයක් නොමැති නිසාය."
බර්නින්ලියෝ

16

පහත සඳහන් දෑ උත්සාහ කරන්න:

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

5
උත්සාහ කරන්න මෙම පිළිතුරු ස්ටැක් ඕවර්ෆ්ලෝ හි අඩු අගයක් ඇති බැවින් ඒවා OP සහ අනාගත පර්යේෂකයන් දහස් ගණනක් දැනුවත් කිරීමට ඉතා අල්පය. විසඳුම ක්‍රියාත්මක වන ආකාරය සහ එය හොඳ අදහසක් වන්නේ මන්ද යන්න ඇතුළත් කිරීමට කරුණාකර මෙම පිළිතුර සංස්කරණය කරන්න.
mickmackusa

1
ගැලපෙන ක්ෂේත්‍ර යතුරු නොවන්නේ නම් පරිපූර්ණ විසඳුම ..!
ලියෝ

6

ඔබට UNIQUEදර්ශකයක් තිබේ නම් ON DUPLICATE KEYහෝ එය සමඟ පරීක්ෂා කළ හැකි පිළිතුරු කිහිපයක් තිබේ INSERT IGNORE. එය සැමවිටම එසේ නොවන UNIQUEඅතර දිග සීමාවක් (බයිට් 1000) ඇති බැවින් ඔබට එය වෙනස් කිරීමට නොහැකි වනු ඇත. උදාහරණයක් ලෙස, මට වර්ඩ්ප්‍රෙස් ( wp_postmeta) හි පාර-දත්ත සමඟ වැඩ කිරීමට සිදුවිය .

මම අවසානයේ එය විමසුම් දෙකකින් විසඳුවා:

UPDATE wp_postmeta SET meta_value = ? WHERE meta_key = ? AND post_id = ?;
INSERT INTO wp_postmeta (post_id, meta_key, meta_value) SELECT DISTINCT ?, ?, ? FROM wp_postmeta WHERE NOT EXISTS(SELECT * FROM wp_postmeta WHERE meta_key = ? AND post_id = ?);

විමසුම 1 යනු UPDATEප්‍රශ්නාර්ථයේ දත්ත කට්ටලය නොමැති විට කිසිදු බලපෑමක් නොමැති සාමාන්‍ය විමසුමකි. විමසුම 2 යනු INSERTa මත රඳා පවතින NOT EXISTS, එනම් INSERTඑය ක්‍රියාත්මක වන්නේ දත්ත කට්ටලය නොපවතින විට පමණි.


3

සඳහන් කළ යුතු දෙයක් නම්, ප්‍රකාශය සාර්ථකද, සාමාන්‍ය INSERT එකක් මෙන් නොවේද යන්න INSERT IGNORE තවමත් ප්‍රාථමික යතුර වැඩි කරයි.

මෙය ඔබගේ ප්‍රාථමික යතුරු වල හිඩැස් ඇති කරවන අතර එමඟින් ක්‍රමලේඛකයෙකු මානසිකව අස්ථාවර විය හැකිය. නැතහොත් ඔබගේ යෙදුම දුර්වල ලෙස නිර්මාණය කර ඇති අතර එය වර්ධක ප්‍රාථමික යතුරු මත රඳා පවතී නම් එය හිසරදයක් විය හැකිය.

සොයා බලන්න innodb_autoinc_lock_mode = 0(සේවාදායක සැකසුම, සහ සුළු කාර්ය සාධන පහරක් සමඟ පැමිණේ), නැතහොත් ඔබේ විමසුම අසාර්ථක නොවන බවට වග බලා ගැනීමට පළමුව SELECT භාවිතා කරන්න (එය කාර්ය සාධන පහරක් සහ අමතර කේතයක් සමඟ ද පැමිණේ).


“ඔබේ ප්‍රාථමික යතුරු වල හිඩැස්” - විභව විය හැකි වුවද - “ක්‍රමලේඛකයෙකු මානසිකව අස්ථාවර වන්නේ” ඇයි? ප්‍රාථමික යතුරු වල සෑම විටම හිඩැස් ඇතිවේ - ඔබ වාර්තාවක් මකා දැමූ සෑම අවස්ථාවකම, උදාහරණයක් ලෙස.
වොරන්

SELECTපරාජයන්ගෙන් පටන් ගෙන විශාල කණ්ඩායමක් භාරදීමේ සම්පූර්ණ අරමුණ පරාජය කිරීම INSERTසහ අනුපිටපත් ගැන කරදර වීමට අකමැති වීම.
වොරන්

2

නොදන්නා ප්‍රාථමික යතුරකින් තොරව යාවත්කාලීන කිරීම හෝ ඇතුළත් කිරීම

ඔබට දැනටමත් අද්විතීය හෝ ප්‍රාථමික යතුරක් තිබේ නම්, අනෙක් පිළිතුරු එක්කෝ INSERT INTO ... ON DUPLICATE KEY UPDATE ...හෝ සමඟREPLACE INTO ... දඩ (- මේ අනුව අර්ධ වශයෙන් දැනට පවතින වටිනාකම් යාවත්කාලීන නොවේ දමයි බවට විස්ථාපනය පවතී පසුව රැසක් නම් සටහනක්) වැඩ කළ යුතුයි.

නමුත් ඔබට some_column_idසහ සඳහා අගයන් තිබේ නම් some_type, එම සංයෝජනය අද්විතීය බව දන්නා කරුණකි. ඔබට අවශ්‍ය some_valueනම් යාවත්කාලීන කිරීමට හෝ නොපවතී නම් ඇතුළු කිරීමට ඔබට අවශ්‍යය . ඔබට එය එක් විමසුමකින් කළ යුතුය (ගනුදෙනුවක් භාවිතා කිරීමෙන් වළකින්න). මෙය විසඳුමක් විය හැකිය:

INSERT INTO my_table (id, some_column_id, some_type, some_value)
SELECT t.id, t.some_column_id, t.some_type, t.some_value
FROM (
    SELECT id, some_column_id, some_type, some_value
    FROM my_table
    WHERE some_column_id = ? AND some_type = ?
    UNION ALL
    SELECT s.id, s.some_column_id, s.some_type, s.some_value
    FROM (SELECT NULL AS id, ? AS some_column_id, ? AS some_type, ? AS some_value) AS s
) AS t
LIMIT 1
ON DUPLICATE KEY UPDATE
some_value = ?

මූලික වශයෙන්, විමසුම මේ ආකාරයෙන් ක්‍රියාත්මක කරයි (පෙනෙන ආකාරයට වඩා අඩු සංකීර්ණ):

  • WHEREවගන්ති ගැලපීම හරහා පවතින පේළියක් තෝරන්න .
  • sතීරු අගයන් පැහැදිලිව ලබා දී ඇති විභව නව පේළියක් (වගුව ) සමඟ එම ප්‍රති result ලය ඒකාබද්ධ කරන්න (s.id යනු NULL, එබැවින් එය නව ස්වයංක්‍රීය වර්ධක හඳුනාගැනීමක් ජනනය කරනු ඇත).
  • දැනට පවතින පේළිය සොයා නම්, එසේ නම් මේසයෙන් හැකි නව පේළියක් sඉවත්කෙරෙනු ඇත (සීමාව 1 මේසය මත නිසා t), සහ එය හැම විටම පුපුරවා හරිනු ඇත ON DUPLICATE KEYහැකි වනු UPDATEඇතිsome_value තීරුව.
  • පවතින පේළියක් සොයාගත නොහැකි නම්, විභව නව පේළිය ඇතුල් කරනු ලැබේ (වගුව අනුව s).

සටහන: සබැඳි දත්ත ගබඩාවක සෑම වගුවකටම අවම වශයෙන් ප්‍රාථමික ස්වයංක්‍රීය වර්ධක idතීරුවක් තිබිය යුතුය . ඔබට මෙය නොමැති නම්, බැලූ බැල්මට ඔබට එය අවශ්‍ය නොවන විට පවා එය එක් කරන්න. මෙම "උපක්රමය" සඳහා එය අනිවාර්යයෙන්ම අවශ්ය වේ.


තවත් පිළිතුරු සපයන්නන් කිහිප දෙනෙකු INSERT INTO ... SELECT FROMආකෘතියක් ඉදිරිපත් කර ඇත. ඔබත් එසේ කළේ ඇයි?
වොරන්

2
@warren එක්කෝ ඔබ මගේ පිළිතුර කියවා නැත, ඔබට එය තේරෙන්නේ නැත, නැතහොත් මම එය නිසි ලෙස පැහැදිලි කර නැත. ඕනෑම අවස්ථාවක, මම පහත සඳහන් කරුණු අවධාරණය කරමි: මෙය සාමාන්‍ය INSERT INTO... SELECT FROM...විසඳුමක් පමණක් නොවේ. කරුණාකර මට සමාන පිළිතුරකට සබැඳියක් යොමු කරන්න, ඔබට එය සොයාගත හැකි නම් මම මෙම පිළිතුර මකා දමමි, එසේ නොමැතිනම් ඔබ මගේ පිළිතුර (ගනුදෙනුව?) ඉහළ නංවයි. ඔබ සම්බන්ධ කිරීමට යන පිළිතුර 1 විමසුමක් (යාවත්කාලීන + ඇතුළු කිරීම සඳහා) පමණක් භාවිතා කරන බව තහවුරු කර ගැනීමට වග බලා ගන්න, කිසිදු ගනුදෙනුවක් සිදු නොවන අතර අද්විතීය යැයි දන්නා ඕනෑම තීරු එකතුවක් ඉලක්ක කිරීමට හැකියාවක් ඇත (එබැවින් වෙන වෙනම තීරු නැත අද්විතීය විය යුතුය).
යේටි
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.