[{"data":1,"prerenderedAt":1585},["ShallowReactive",2],{"blog-\u002Fblog\u002Fsql-insert-update-delete-dml":3},{"id":4,"title":5,"body":6,"description":1571,"difficulty":1572,"extension":1573,"framework":1574,"frameworkSlug":43,"meta":1575,"navigation":100,"order":52,"path":1576,"qaPath":1577,"seo":1578,"stem":1579,"subtopic":1580,"topic":1581,"topicSlug":1582,"updated":1583,"__hash__":1584},"blog\u002Fblog\u002Fsql-insert-update-delete-dml.md","SQL INSERT, UPDATE, DELETE — DML That Stays Safe at Scale",{"type":7,"value":8,"toc":1560},"minimark",[9,14,34,38,270,274,277,687,691,703,928,932,935,1123,1127,1139,1288,1292,1376,1417,1421,1428,1524,1528,1556],[10,11,13],"h2",{"id":12},"the-three-write-operations","The three write operations",[15,16,17,21,22,25,26,29,30,33],"p",{},[18,19,20],"strong",{},"INSERT"," adds new rows, ",[18,23,24],{},"UPDATE"," modifies existing ones, ",[18,27,28],{},"DELETE"," removes\nthem. Together they are called ",[18,31,32],{},"DML"," (Data Manipulation Language). Unlike DDL,\nDML runs inside a transaction and can be rolled back.",[10,35,37],{"id":36},"insert-adding-rows","INSERT — adding rows",[39,40,45],"pre",{"className":41,"code":42,"language":43,"meta":44,"style":44},"language-sql shiki shiki-themes github-light github-dark","-- Single row\nINSERT INTO customers (email, display_name, country_code)\nVALUES ('alice@example.com', 'Alice Brown', 'GB');\n\n-- Multiple rows in one statement (faster than many single-row INSERTs)\nINSERT INTO products (product_name, category, unit_price)\nVALUES\n    ('Mechanical Keyboard', 'Electronics', 89.99),\n    ('Wireless Mouse',      'Electronics', 34.99),\n    ('Standing Desk Mat',   'Office',      29.99);\n\n-- Insert from a SELECT (copy rows between tables)\nINSERT INTO archived_orders (id, customer_id, total_amount, created_at)\nSELECT id, customer_id, total_amount, created_at\nFROM   orders\nWHERE  created_at \u003C '2025-01-01'\n  AND  status = 'completed';\n","sql","",[46,47,48,57,68,95,102,108,116,122,151,175,200,205,211,219,228,237,252],"code",{"__ignoreMap":44},[49,50,53],"span",{"class":51,"line":52},"line",1,[49,54,56],{"class":55},"sJ8bj","-- Single row\n",[49,58,60,64],{"class":51,"line":59},2,[49,61,63],{"class":62},"szBVR","INSERT INTO",[49,65,67],{"class":66},"sVt8B"," customers (email, display_name, country_code)\n",[49,69,71,74,77,81,84,87,89,92],{"class":51,"line":70},3,[49,72,73],{"class":62},"VALUES",[49,75,76],{"class":66}," (",[49,78,80],{"class":79},"sZZnC","'alice@example.com'",[49,82,83],{"class":66},", ",[49,85,86],{"class":79},"'Alice Brown'",[49,88,83],{"class":66},[49,90,91],{"class":79},"'GB'",[49,93,94],{"class":66},");\n",[49,96,98],{"class":51,"line":97},4,[49,99,101],{"emptyLinePlaceholder":100},true,"\n",[49,103,105],{"class":51,"line":104},5,[49,106,107],{"class":55},"-- Multiple rows in one statement (faster than many single-row INSERTs)\n",[49,109,111,113],{"class":51,"line":110},6,[49,112,63],{"class":62},[49,114,115],{"class":66}," products (product_name, category, unit_price)\n",[49,117,119],{"class":51,"line":118},7,[49,120,121],{"class":62},"VALUES\n",[49,123,125,128,131,133,136,138,142,145,148],{"class":51,"line":124},8,[49,126,127],{"class":66},"    (",[49,129,130],{"class":79},"'Mechanical Keyboard'",[49,132,83],{"class":66},[49,134,135],{"class":79},"'Electronics'",[49,137,83],{"class":66},[49,139,141],{"class":140},"sj4cs","89",[49,143,144],{"class":66},".",[49,146,147],{"class":140},"99",[49,149,150],{"class":66},"),\n",[49,152,154,156,159,162,164,166,169,171,173],{"class":51,"line":153},9,[49,155,127],{"class":66},[49,157,158],{"class":79},"'Wireless Mouse'",[49,160,161],{"class":66},",      ",[49,163,135],{"class":79},[49,165,83],{"class":66},[49,167,168],{"class":140},"34",[49,170,144],{"class":66},[49,172,147],{"class":140},[49,174,150],{"class":66},[49,176,178,180,183,186,189,191,194,196,198],{"class":51,"line":177},10,[49,179,127],{"class":66},[49,181,182],{"class":79},"'Standing Desk Mat'",[49,184,185],{"class":66},",   ",[49,187,188],{"class":79},"'Office'",[49,190,161],{"class":66},[49,192,193],{"class":140},"29",[49,195,144],{"class":66},[49,197,147],{"class":140},[49,199,94],{"class":66},[49,201,203],{"class":51,"line":202},11,[49,204,101],{"emptyLinePlaceholder":100},[49,206,208],{"class":51,"line":207},12,[49,209,210],{"class":55},"-- Insert from a SELECT (copy rows between tables)\n",[49,212,214,216],{"class":51,"line":213},13,[49,215,63],{"class":62},[49,217,218],{"class":66}," archived_orders (id, customer_id, total_amount, created_at)\n",[49,220,222,225],{"class":51,"line":221},14,[49,223,224],{"class":62},"SELECT",[49,226,227],{"class":66}," id, customer_id, total_amount, created_at\n",[49,229,231,234],{"class":51,"line":230},15,[49,232,233],{"class":62},"FROM",[49,235,236],{"class":66},"   orders\n",[49,238,240,243,246,249],{"class":51,"line":239},16,[49,241,242],{"class":62},"WHERE",[49,244,245],{"class":66},"  created_at ",[49,247,248],{"class":62},"\u003C",[49,250,251],{"class":79}," '2025-01-01'\n",[49,253,255,258,261,264,267],{"class":51,"line":254},17,[49,256,257],{"class":62},"  AND",[49,259,260],{"class":62},"  status",[49,262,263],{"class":62}," =",[49,265,266],{"class":79}," 'completed'",[49,268,269],{"class":66},";\n",[10,271,273],{"id":272},"upsert-insert-or-update-on-conflict","UPSERT — insert or update on conflict",[15,275,276],{},"A common pattern: insert a row if it does not exist, update it if it does.\nWithout a specific operator, this requires a SELECT first — which introduces a\nrace condition. Use the database's native UPSERT instead.",[39,278,280],{"className":41,"code":279,"language":43,"meta":44,"style":44},"-- Postgres: INSERT ... ON CONFLICT\nINSERT INTO product_inventory (product_id, warehouse_id, stock_qty)\nVALUES (42, 3, 100)\nON CONFLICT (product_id, warehouse_id) DO UPDATE\n    SET stock_qty  = product_inventory.stock_qty + EXCLUDED.stock_qty,\n        updated_at = NOW();\n-- EXCLUDED refers to the row that was rejected (the proposed INSERT values)\n\n-- Postgres: do nothing if a duplicate exists\nINSERT INTO user_settings (user_id, setting_key, setting_value)\nVALUES (1001, 'theme', 'dark')\nON CONFLICT (user_id, setting_key) DO NOTHING;\n\n-- MySQL: INSERT ... ON DUPLICATE KEY UPDATE\nINSERT INTO product_inventory (product_id, warehouse_id, stock_qty)\nVALUES (42, 3, 100)\nON DUPLICATE KEY UPDATE stock_qty = stock_qty + VALUES(stock_qty);\n\n-- SQL Server: MERGE\nMERGE INTO product_inventory AS tgt\nUSING (SELECT 42 AS product_id, 3 AS warehouse_id, 100 AS qty) AS src\n    ON tgt.product_id = src.product_id AND tgt.warehouse_id = src.warehouse_id\nWHEN MATCHED THEN\n    UPDATE SET tgt.stock_qty = tgt.stock_qty + src.qty\nWHEN NOT MATCHED THEN\n    INSERT (product_id, warehouse_id, stock_qty) VALUES (src.product_id, src.warehouse_id, src.qty);\n",[46,281,282,287,294,316,327,359,372,377,381,386,393,414,421,425,430,436,454,483,488,494,512,550,592,604,636,648],{"__ignoreMap":44},[49,283,284],{"class":51,"line":52},[49,285,286],{"class":55},"-- Postgres: INSERT ... ON CONFLICT\n",[49,288,289,291],{"class":51,"line":59},[49,290,63],{"class":62},[49,292,293],{"class":66}," product_inventory (product_id, warehouse_id, stock_qty)\n",[49,295,296,298,300,303,305,308,310,313],{"class":51,"line":70},[49,297,73],{"class":62},[49,299,76],{"class":66},[49,301,302],{"class":140},"42",[49,304,83],{"class":66},[49,306,307],{"class":140},"3",[49,309,83],{"class":66},[49,311,312],{"class":140},"100",[49,314,315],{"class":66},")\n",[49,317,318,321,324],{"class":51,"line":97},[49,319,320],{"class":62},"ON",[49,322,323],{"class":66}," CONFLICT (product_id, warehouse_id) DO ",[49,325,326],{"class":62},"UPDATE\n",[49,328,329,332,335,338,341,343,346,349,352,354,356],{"class":51,"line":104},[49,330,331],{"class":62},"    SET",[49,333,334],{"class":66}," stock_qty  ",[49,336,337],{"class":62},"=",[49,339,340],{"class":140}," product_inventory",[49,342,144],{"class":66},[49,344,345],{"class":140},"stock_qty",[49,347,348],{"class":62}," +",[49,350,351],{"class":140}," EXCLUDED",[49,353,144],{"class":66},[49,355,345],{"class":140},[49,357,358],{"class":66},",\n",[49,360,361,364,366,369],{"class":51,"line":110},[49,362,363],{"class":66},"        updated_at ",[49,365,337],{"class":62},[49,367,368],{"class":62}," NOW",[49,370,371],{"class":66},"();\n",[49,373,374],{"class":51,"line":118},[49,375,376],{"class":55},"-- EXCLUDED refers to the row that was rejected (the proposed INSERT values)\n",[49,378,379],{"class":51,"line":124},[49,380,101],{"emptyLinePlaceholder":100},[49,382,383],{"class":51,"line":153},[49,384,385],{"class":55},"-- Postgres: do nothing if a duplicate exists\n",[49,387,388,390],{"class":51,"line":177},[49,389,63],{"class":62},[49,391,392],{"class":66}," user_settings (user_id, setting_key, setting_value)\n",[49,394,395,397,399,402,404,407,409,412],{"class":51,"line":202},[49,396,73],{"class":62},[49,398,76],{"class":66},[49,400,401],{"class":140},"1001",[49,403,83],{"class":66},[49,405,406],{"class":79},"'theme'",[49,408,83],{"class":66},[49,410,411],{"class":79},"'dark'",[49,413,315],{"class":66},[49,415,416,418],{"class":51,"line":207},[49,417,320],{"class":62},[49,419,420],{"class":66}," CONFLICT (user_id, setting_key) DO NOTHING;\n",[49,422,423],{"class":51,"line":213},[49,424,101],{"emptyLinePlaceholder":100},[49,426,427],{"class":51,"line":221},[49,428,429],{"class":55},"-- MySQL: INSERT ... ON DUPLICATE KEY UPDATE\n",[49,431,432,434],{"class":51,"line":230},[49,433,63],{"class":62},[49,435,293],{"class":66},[49,437,438,440,442,444,446,448,450,452],{"class":51,"line":239},[49,439,73],{"class":62},[49,441,76],{"class":66},[49,443,302],{"class":140},[49,445,83],{"class":66},[49,447,307],{"class":140},[49,449,83],{"class":66},[49,451,312],{"class":140},[49,453,315],{"class":66},[49,455,456,458,461,464,467,470,472,474,477,480],{"class":51,"line":254},[49,457,320],{"class":62},[49,459,460],{"class":66}," DUPLICATE ",[49,462,463],{"class":62},"KEY",[49,465,466],{"class":62}," UPDATE",[49,468,469],{"class":66}," stock_qty ",[49,471,337],{"class":62},[49,473,469],{"class":66},[49,475,476],{"class":62},"+",[49,478,479],{"class":62}," VALUES",[49,481,482],{"class":66},"(stock_qty);\n",[49,484,486],{"class":51,"line":485},18,[49,487,101],{"emptyLinePlaceholder":100},[49,489,491],{"class":51,"line":490},19,[49,492,493],{"class":55},"-- SQL Server: MERGE\n",[49,495,497,500,503,506,509],{"class":51,"line":496},20,[49,498,499],{"class":62},"MERGE",[49,501,502],{"class":62}," INTO",[49,504,505],{"class":66}," product_inventory ",[49,507,508],{"class":62},"AS",[49,510,511],{"class":66}," tgt\n",[49,513,515,518,520,522,525,528,531,533,535,538,540,542,545,547],{"class":51,"line":514},21,[49,516,517],{"class":62},"USING",[49,519,76],{"class":66},[49,521,224],{"class":62},[49,523,524],{"class":140}," 42",[49,526,527],{"class":62}," AS",[49,529,530],{"class":66}," product_id, ",[49,532,307],{"class":140},[49,534,527],{"class":62},[49,536,537],{"class":66}," warehouse_id, ",[49,539,312],{"class":140},[49,541,527],{"class":62},[49,543,544],{"class":66}," qty) ",[49,546,508],{"class":62},[49,548,549],{"class":66}," src\n",[49,551,553,556,559,561,564,566,569,571,573,576,578,580,583,585,587,589],{"class":51,"line":552},22,[49,554,555],{"class":62},"    ON",[49,557,558],{"class":140}," tgt",[49,560,144],{"class":66},[49,562,563],{"class":140},"product_id",[49,565,263],{"class":62},[49,567,568],{"class":140}," src",[49,570,144],{"class":66},[49,572,563],{"class":140},[49,574,575],{"class":62}," AND",[49,577,558],{"class":140},[49,579,144],{"class":66},[49,581,582],{"class":140},"warehouse_id",[49,584,263],{"class":62},[49,586,568],{"class":140},[49,588,144],{"class":66},[49,590,591],{"class":140},"warehouse_id\n",[49,593,595,598,601],{"class":51,"line":594},23,[49,596,597],{"class":62},"WHEN",[49,599,600],{"class":62}," MATCHED",[49,602,603],{"class":62}," THEN\n",[49,605,607,610,613,615,617,619,621,623,625,627,629,631,633],{"class":51,"line":606},24,[49,608,609],{"class":62},"    UPDATE",[49,611,612],{"class":62}," SET",[49,614,558],{"class":140},[49,616,144],{"class":66},[49,618,345],{"class":140},[49,620,263],{"class":62},[49,622,558],{"class":140},[49,624,144],{"class":66},[49,626,345],{"class":140},[49,628,348],{"class":62},[49,630,568],{"class":140},[49,632,144],{"class":66},[49,634,635],{"class":140},"qty\n",[49,637,639,641,644,646],{"class":51,"line":638},25,[49,640,597],{"class":62},[49,642,643],{"class":62}," NOT",[49,645,600],{"class":62},[49,647,603],{"class":62},[49,649,651,654,657,659,661,664,666,668,670,672,674,676,678,680,682,685],{"class":51,"line":650},26,[49,652,653],{"class":62},"    INSERT",[49,655,656],{"class":66}," (product_id, warehouse_id, stock_qty) ",[49,658,73],{"class":62},[49,660,76],{"class":66},[49,662,663],{"class":140},"src",[49,665,144],{"class":66},[49,667,563],{"class":140},[49,669,83],{"class":66},[49,671,663],{"class":140},[49,673,144],{"class":66},[49,675,582],{"class":140},[49,677,83],{"class":66},[49,679,663],{"class":140},[49,681,144],{"class":66},[49,683,684],{"class":140},"qty",[49,686,94],{"class":66},[10,688,690],{"id":689},"update-modifying-existing-rows","UPDATE — modifying existing rows",[15,692,693,694,696,697,699,700,702],{},"Always include a ",[46,695,242],{}," clause. An ",[46,698,24],{}," without ",[46,701,242],{}," modifies every row\nin the table.",[39,704,706],{"className":41,"code":705,"language":43,"meta":44,"style":44},"-- Update a single row\nUPDATE orders SET status = 'shipped', updated_at = NOW()\nWHERE id = 10842;\n\n-- Update based on a related table (correlated update)\nUPDATE order_items oi\nSET unit_price = p.unit_price\nFROM products p\nWHERE p.id = oi.product_id\n  AND oi.created_at >= '2026-01-01';\n\n-- Conditional update (apply a discount to premium customers)\nUPDATE orders\nSET total_amount = total_amount * 0.90\nWHERE customer_id IN (\n    SELECT id FROM customers WHERE account_type = 'premium'\n)\nAND created_at >= '2026-06-01';\n",[46,707,708,713,741,755,759,764,771,788,795,816,835,839,844,851,873,886,908,912],{"__ignoreMap":44},[49,709,710],{"class":51,"line":52},[49,711,712],{"class":55},"-- Update a single row\n",[49,714,715,717,720,723,726,728,731,734,736,738],{"class":51,"line":59},[49,716,24],{"class":62},[49,718,719],{"class":66}," orders ",[49,721,722],{"class":62},"SET",[49,724,725],{"class":62}," status",[49,727,263],{"class":62},[49,729,730],{"class":79}," 'shipped'",[49,732,733],{"class":66},", updated_at ",[49,735,337],{"class":62},[49,737,368],{"class":62},[49,739,740],{"class":66},"()\n",[49,742,743,745,748,750,753],{"class":51,"line":70},[49,744,242],{"class":62},[49,746,747],{"class":66}," id ",[49,749,337],{"class":62},[49,751,752],{"class":140}," 10842",[49,754,269],{"class":66},[49,756,757],{"class":51,"line":97},[49,758,101],{"emptyLinePlaceholder":100},[49,760,761],{"class":51,"line":104},[49,762,763],{"class":55},"-- Update based on a related table (correlated update)\n",[49,765,766,768],{"class":51,"line":110},[49,767,24],{"class":62},[49,769,770],{"class":66}," order_items oi\n",[49,772,773,775,778,780,783,785],{"class":51,"line":118},[49,774,722],{"class":62},[49,776,777],{"class":66}," unit_price ",[49,779,337],{"class":62},[49,781,782],{"class":140}," p",[49,784,144],{"class":66},[49,786,787],{"class":140},"unit_price\n",[49,789,790,792],{"class":51,"line":124},[49,791,233],{"class":62},[49,793,794],{"class":66}," products p\n",[49,796,797,799,801,803,806,808,811,813],{"class":51,"line":153},[49,798,242],{"class":62},[49,800,782],{"class":140},[49,802,144],{"class":66},[49,804,805],{"class":140},"id",[49,807,263],{"class":62},[49,809,810],{"class":140}," oi",[49,812,144],{"class":66},[49,814,815],{"class":140},"product_id\n",[49,817,818,820,822,824,827,830,833],{"class":51,"line":177},[49,819,257],{"class":62},[49,821,810],{"class":140},[49,823,144],{"class":66},[49,825,826],{"class":140},"created_at",[49,828,829],{"class":62}," >=",[49,831,832],{"class":79}," '2026-01-01'",[49,834,269],{"class":66},[49,836,837],{"class":51,"line":202},[49,838,101],{"emptyLinePlaceholder":100},[49,840,841],{"class":51,"line":207},[49,842,843],{"class":55},"-- Conditional update (apply a discount to premium customers)\n",[49,845,846,848],{"class":51,"line":213},[49,847,24],{"class":62},[49,849,850],{"class":66}," orders\n",[49,852,853,855,858,860,862,865,868,870],{"class":51,"line":221},[49,854,722],{"class":62},[49,856,857],{"class":66}," total_amount ",[49,859,337],{"class":62},[49,861,857],{"class":66},[49,863,864],{"class":62},"*",[49,866,867],{"class":140}," 0",[49,869,144],{"class":66},[49,871,872],{"class":140},"90\n",[49,874,875,877,880,883],{"class":51,"line":230},[49,876,242],{"class":62},[49,878,879],{"class":66}," customer_id ",[49,881,882],{"class":62},"IN",[49,884,885],{"class":66}," (\n",[49,887,888,891,893,895,898,900,903,905],{"class":51,"line":239},[49,889,890],{"class":62},"    SELECT",[49,892,747],{"class":66},[49,894,233],{"class":62},[49,896,897],{"class":66}," customers ",[49,899,242],{"class":62},[49,901,902],{"class":66}," account_type ",[49,904,337],{"class":62},[49,906,907],{"class":79}," 'premium'\n",[49,909,910],{"class":51,"line":254},[49,911,315],{"class":66},[49,913,914,917,920,923,926],{"class":51,"line":485},[49,915,916],{"class":62},"AND",[49,918,919],{"class":66}," created_at ",[49,921,922],{"class":62},">=",[49,924,925],{"class":79}," '2026-06-01'",[49,927,269],{"class":66},[10,929,931],{"id":930},"batching-large-updates","Batching large updates",[15,933,934],{},"Updating millions of rows in one statement holds a lock for the entire duration,\nblocking reads and writes. Batch it:",[39,936,938],{"className":41,"code":937,"language":43,"meta":44,"style":44},"-- Batch update in chunks of 10,000 rows (Postgres)\nDO $$\nDECLARE\n    updated INT := 1;\nBEGIN\n    WHILE updated > 0 LOOP\n        UPDATE orders\n        SET    status = 'archived'\n        WHERE  id IN (\n            SELECT id FROM orders\n            WHERE  status = 'completed'\n              AND  created_at \u003C '2025-01-01'\n            LIMIT  10000\n        );\n        GET DIAGNOSTICS updated = ROW_COUNT;\n        PERFORM pg_sleep(0.1);  -- brief pause to allow other transactions\n    END LOOP;\nEND $$;\n",[46,939,940,945,950,955,973,978,994,1001,1014,1026,1037,1049,1060,1068,1073,1086,1105,1115],{"__ignoreMap":44},[49,941,942],{"class":51,"line":52},[49,943,944],{"class":55},"-- Batch update in chunks of 10,000 rows (Postgres)\n",[49,946,947],{"class":51,"line":59},[49,948,949],{"class":66},"DO $$\n",[49,951,952],{"class":51,"line":70},[49,953,954],{"class":62},"DECLARE\n",[49,956,957,960,963,966,968,971],{"class":51,"line":97},[49,958,959],{"class":66},"    updated ",[49,961,962],{"class":62},"INT",[49,964,965],{"class":66}," :",[49,967,337],{"class":62},[49,969,970],{"class":140}," 1",[49,972,269],{"class":66},[49,974,975],{"class":51,"line":104},[49,976,977],{"class":62},"BEGIN\n",[49,979,980,983,986,989,991],{"class":51,"line":110},[49,981,982],{"class":62},"    WHILE",[49,984,985],{"class":66}," updated ",[49,987,988],{"class":62},">",[49,990,867],{"class":140},[49,992,993],{"class":62}," LOOP\n",[49,995,996,999],{"class":51,"line":118},[49,997,998],{"class":62},"        UPDATE",[49,1000,850],{"class":66},[49,1002,1003,1006,1009,1011],{"class":51,"line":124},[49,1004,1005],{"class":62},"        SET",[49,1007,1008],{"class":62},"    status",[49,1010,263],{"class":62},[49,1012,1013],{"class":79}," 'archived'\n",[49,1015,1016,1019,1022,1024],{"class":51,"line":153},[49,1017,1018],{"class":62},"        WHERE",[49,1020,1021],{"class":66},"  id ",[49,1023,882],{"class":62},[49,1025,885],{"class":66},[49,1027,1028,1031,1033,1035],{"class":51,"line":177},[49,1029,1030],{"class":62},"            SELECT",[49,1032,747],{"class":66},[49,1034,233],{"class":62},[49,1036,850],{"class":66},[49,1038,1039,1042,1044,1046],{"class":51,"line":202},[49,1040,1041],{"class":62},"            WHERE",[49,1043,260],{"class":62},[49,1045,263],{"class":62},[49,1047,1048],{"class":79}," 'completed'\n",[49,1050,1051,1054,1056,1058],{"class":51,"line":207},[49,1052,1053],{"class":62},"              AND",[49,1055,245],{"class":66},[49,1057,248],{"class":62},[49,1059,251],{"class":79},[49,1061,1062,1065],{"class":51,"line":213},[49,1063,1064],{"class":62},"            LIMIT",[49,1066,1067],{"class":140},"  10000\n",[49,1069,1070],{"class":51,"line":221},[49,1071,1072],{"class":66},"        );\n",[49,1074,1075,1078,1081,1083],{"class":51,"line":230},[49,1076,1077],{"class":62},"        GET",[49,1079,1080],{"class":66}," DIAGNOSTICS updated ",[49,1082,337],{"class":62},[49,1084,1085],{"class":66}," ROW_COUNT;\n",[49,1087,1088,1091,1094,1096,1099,1102],{"class":51,"line":239},[49,1089,1090],{"class":66},"        PERFORM pg_sleep(",[49,1092,1093],{"class":140},"0",[49,1095,144],{"class":66},[49,1097,1098],{"class":140},"1",[49,1100,1101],{"class":66},");  ",[49,1103,1104],{"class":55},"-- brief pause to allow other transactions\n",[49,1106,1107,1110,1113],{"class":51,"line":254},[49,1108,1109],{"class":62},"    END",[49,1111,1112],{"class":62}," LOOP",[49,1114,269],{"class":66},[49,1116,1117,1120],{"class":51,"line":485},[49,1118,1119],{"class":62},"END",[49,1121,1122],{"class":66}," $$;\n",[10,1124,1126],{"id":1125},"delete-removing-rows-safely","DELETE — removing rows safely",[15,1128,1129,1130,1132,1133,1135,1136,1138],{},"Like ",[46,1131,24],{},", always include ",[46,1134,242],{},". Test with ",[46,1137,224],{}," first.",[39,1140,1142],{"className":41,"code":1141,"language":43,"meta":44,"style":44},"-- Verify before deleting\nSELECT COUNT(*) FROM sessions WHERE expires_at \u003C NOW();\n\n-- Then delete\nDELETE FROM sessions WHERE expires_at \u003C NOW();\n\n-- Delete with a JOIN condition (Postgres syntax)\nDELETE FROM order_items oi\nUSING orders o\nWHERE oi.order_id = o.id\n  AND o.status = 'cancelled'\n  AND o.created_at \u003C '2025-01-01';\n",[46,1143,1144,1149,1181,1185,1190,1209,1213,1218,1226,1233,1254,1270],{"__ignoreMap":44},[49,1145,1146],{"class":51,"line":52},[49,1147,1148],{"class":55},"-- Verify before deleting\n",[49,1150,1151,1153,1156,1159,1161,1164,1166,1169,1172,1175,1177,1179],{"class":51,"line":59},[49,1152,224],{"class":62},[49,1154,1155],{"class":140}," COUNT",[49,1157,1158],{"class":66},"(",[49,1160,864],{"class":62},[49,1162,1163],{"class":66},") ",[49,1165,233],{"class":62},[49,1167,1168],{"class":62}," sessions",[49,1170,1171],{"class":62}," WHERE",[49,1173,1174],{"class":66}," expires_at ",[49,1176,248],{"class":62},[49,1178,368],{"class":62},[49,1180,371],{"class":66},[49,1182,1183],{"class":51,"line":70},[49,1184,101],{"emptyLinePlaceholder":100},[49,1186,1187],{"class":51,"line":97},[49,1188,1189],{"class":55},"-- Then delete\n",[49,1191,1192,1194,1197,1199,1201,1203,1205,1207],{"class":51,"line":104},[49,1193,28],{"class":62},[49,1195,1196],{"class":62}," FROM",[49,1198,1168],{"class":62},[49,1200,1171],{"class":62},[49,1202,1174],{"class":66},[49,1204,248],{"class":62},[49,1206,368],{"class":62},[49,1208,371],{"class":66},[49,1210,1211],{"class":51,"line":110},[49,1212,101],{"emptyLinePlaceholder":100},[49,1214,1215],{"class":51,"line":118},[49,1216,1217],{"class":55},"-- Delete with a JOIN condition (Postgres syntax)\n",[49,1219,1220,1222,1224],{"class":51,"line":124},[49,1221,28],{"class":62},[49,1223,1196],{"class":62},[49,1225,770],{"class":66},[49,1227,1228,1230],{"class":51,"line":153},[49,1229,517],{"class":62},[49,1231,1232],{"class":66}," orders o\n",[49,1234,1235,1237,1239,1241,1244,1246,1249,1251],{"class":51,"line":177},[49,1236,242],{"class":62},[49,1238,810],{"class":140},[49,1240,144],{"class":66},[49,1242,1243],{"class":140},"order_id",[49,1245,263],{"class":62},[49,1247,1248],{"class":140}," o",[49,1250,144],{"class":66},[49,1252,1253],{"class":140},"id\n",[49,1255,1256,1258,1260,1262,1265,1267],{"class":51,"line":202},[49,1257,257],{"class":62},[49,1259,1248],{"class":140},[49,1261,144],{"class":66},[49,1263,1264],{"class":140},"status",[49,1266,263],{"class":62},[49,1268,1269],{"class":79}," 'cancelled'\n",[49,1271,1272,1274,1276,1278,1280,1283,1286],{"class":51,"line":207},[49,1273,257],{"class":62},[49,1275,1248],{"class":140},[49,1277,144],{"class":66},[49,1279,826],{"class":140},[49,1281,1282],{"class":62}," \u003C",[49,1284,1285],{"class":79}," '2025-01-01'",[49,1287,269],{"class":66},[10,1289,1291],{"id":1290},"delete-vs-truncate","DELETE vs TRUNCATE",[1293,1294,1295,1309],"table",{},[1296,1297,1298],"thead",{},[1299,1300,1301,1304,1306],"tr",{},[1302,1303],"th",{},[1302,1305,28],{},[1302,1307,1308],{},"TRUNCATE",[1310,1311,1312,1324,1334,1344,1354,1365],"tbody",{},[1299,1313,1314,1318,1321],{},[1315,1316,1317],"td",{},"Logs each row",[1315,1319,1320],{},"Yes",[1315,1322,1323],{},"No (minimal logging)",[1299,1325,1326,1329,1331],{},[1315,1327,1328],{},"Can be rolled back",[1315,1330,1320],{},[1315,1332,1333],{},"Yes (Postgres); No (MySQL)",[1299,1335,1336,1339,1341],{},[1315,1337,1338],{},"Triggers fire",[1315,1340,1320],{},[1315,1342,1343],{},"No (usually)",[1299,1345,1346,1349,1351],{},[1315,1347,1348],{},"Respects WHERE",[1315,1350,1320],{},[1315,1352,1353],{},"No (all rows)",[1299,1355,1356,1359,1362],{},[1315,1357,1358],{},"Speed on large tables",[1315,1360,1361],{},"Slow",[1315,1363,1364],{},"Very fast",[1299,1366,1367,1370,1373],{},[1315,1368,1369],{},"Resets sequences\u002Fauto-increment",[1315,1371,1372],{},"No",[1315,1374,1375],{},"Yes (optionally)",[39,1377,1379],{"className":41,"code":1378,"language":43,"meta":44,"style":44},"-- Clear a staging table quickly (no row-by-row logging)\nTRUNCATE TABLE staging_product_import;\n\n-- TRUNCATE with cascade (also truncates referencing tables)\nTRUNCATE TABLE orders CASCADE;  -- also clears order_items\n",[46,1380,1381,1386,1396,1400,1405],{"__ignoreMap":44},[49,1382,1383],{"class":51,"line":52},[49,1384,1385],{"class":55},"-- Clear a staging table quickly (no row-by-row logging)\n",[49,1387,1388,1390,1393],{"class":51,"line":59},[49,1389,1308],{"class":62},[49,1391,1392],{"class":62}," TABLE",[49,1394,1395],{"class":66}," staging_product_import;\n",[49,1397,1398],{"class":51,"line":70},[49,1399,101],{"emptyLinePlaceholder":100},[49,1401,1402],{"class":51,"line":97},[49,1403,1404],{"class":55},"-- TRUNCATE with cascade (also truncates referencing tables)\n",[49,1406,1407,1409,1411,1414],{"class":51,"line":104},[49,1408,1308],{"class":62},[49,1410,1392],{"class":62},[49,1412,1413],{"class":66}," orders CASCADE;  ",[49,1415,1416],{"class":55},"-- also clears order_items\n",[10,1418,1420],{"id":1419},"returning-get-insertedupdateddeleted-values","RETURNING — get inserted\u002Fupdated\u002Fdeleted values",[15,1422,1423,1424,1427],{},"Postgres (and SQL Server with ",[46,1425,1426],{},"OUTPUT",") can return the affected rows without a\nsecond query:",[39,1429,1431],{"className":41,"code":1430,"language":43,"meta":44,"style":44},"-- Get the new order's ID immediately after INSERT\nINSERT INTO orders (customer_id, total_amount)\nVALUES (1001, 249.99)\nRETURNING id, created_at;\n\n-- Update and return the new values\nUPDATE products SET unit_price = unit_price * 1.05\nWHERE category = 'Electronics'\nRETURNING id, product_name, unit_price AS new_price;\n",[46,1432,1433,1438,1445,1464,1469,1473,1478,1502,1514],{"__ignoreMap":44},[49,1434,1435],{"class":51,"line":52},[49,1436,1437],{"class":55},"-- Get the new order's ID immediately after INSERT\n",[49,1439,1440,1442],{"class":51,"line":59},[49,1441,63],{"class":62},[49,1443,1444],{"class":66}," orders (customer_id, total_amount)\n",[49,1446,1447,1449,1451,1453,1455,1458,1460,1462],{"class":51,"line":70},[49,1448,73],{"class":62},[49,1450,76],{"class":66},[49,1452,401],{"class":140},[49,1454,83],{"class":66},[49,1456,1457],{"class":140},"249",[49,1459,144],{"class":66},[49,1461,147],{"class":140},[49,1463,315],{"class":66},[49,1465,1466],{"class":51,"line":97},[49,1467,1468],{"class":66},"RETURNING id, created_at;\n",[49,1470,1471],{"class":51,"line":104},[49,1472,101],{"emptyLinePlaceholder":100},[49,1474,1475],{"class":51,"line":110},[49,1476,1477],{"class":55},"-- Update and return the new values\n",[49,1479,1480,1482,1485,1487,1489,1491,1493,1495,1497,1499],{"class":51,"line":118},[49,1481,24],{"class":62},[49,1483,1484],{"class":66}," products ",[49,1486,722],{"class":62},[49,1488,777],{"class":66},[49,1490,337],{"class":62},[49,1492,777],{"class":66},[49,1494,864],{"class":62},[49,1496,970],{"class":140},[49,1498,144],{"class":66},[49,1500,1501],{"class":140},"05\n",[49,1503,1504,1506,1509,1511],{"class":51,"line":124},[49,1505,242],{"class":62},[49,1507,1508],{"class":66}," category ",[49,1510,337],{"class":62},[49,1512,1513],{"class":79}," 'Electronics'\n",[49,1515,1516,1519,1521],{"class":51,"line":153},[49,1517,1518],{"class":66},"RETURNING id, product_name, unit_price ",[49,1520,508],{"class":62},[49,1522,1523],{"class":66}," new_price;\n",[10,1525,1527],{"id":1526},"recap","Recap",[15,1529,1530,1531,1533,1534,1537,1538,1540,1541,1543,1544,1546,1547,1549,1550,1552,1553,1555],{},"Multi-row ",[46,1532,20],{}," is significantly faster than many single-row statements.\nUse ",[46,1535,1536],{},"ON CONFLICT"," (Postgres) for UPSERT instead of a check-then-insert pattern.\nAlways ",[46,1539,242],{},"-qualify ",[46,1542,24],{}," and ",[46,1545,28],{}," — test with ",[46,1548,224],{}," first on new\nqueries. Batch large updates to avoid long-held locks. Use ",[46,1551,1308],{}," to clear\nstaging tables, ",[46,1554,28],{}," when you need transaction safety or triggers to fire.",[1557,1558,1559],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":44,"searchDepth":59,"depth":59,"links":1561},[1562,1563,1564,1565,1566,1567,1568,1569,1570],{"id":12,"depth":59,"text":13},{"id":36,"depth":59,"text":37},{"id":272,"depth":59,"text":273},{"id":689,"depth":59,"text":690},{"id":930,"depth":59,"text":931},{"id":1125,"depth":59,"text":1126},{"id":1290,"depth":59,"text":1291},{"id":1419,"depth":59,"text":1420},{"id":1526,"depth":59,"text":1527},"SQL DML explained — INSERT with conflict handling, bulk updates, safe deletes, UPSERT patterns, batching, and the difference between DELETE and TRUNCATE.","medium","md","SQL",{},"\u002Fblog\u002Fsql-insert-update-delete-dml","\u002Fsql\u002Fdml\u002Finsert-update-delete",{"title":5,"description":1571},"blog\u002Fsql-insert-update-delete-dml","INSERT, UPDATE & DELETE","Modifying Data","dml","2026-06-20","HrrN_ngr9dCMuju00DMmNX3NvI_z-ruXHd34EOc0udU",1782244088191]