ชื่อตารางเป็นพารามิเตอร์ฟังก์ชัน PostgreSQL


87

ฉันต้องการส่งชื่อตารางเป็นพารามิเตอร์ในฟังก์ชัน Postgres ฉันลองใช้รหัสนี้:

CREATE OR REPLACE FUNCTION some_f(param character varying) RETURNS integer 
AS $$
    BEGIN
    IF EXISTS (select * from quote_ident($1) where quote_ident($1).id=1) THEN
     return 1;
    END IF;
    return 0;
    END;
$$ LANGUAGE plpgsql;

select some_f('table_name');

และฉันได้รับสิ่งนี้:

ERROR:  syntax error at or near "."
LINE 4: ...elect * from quote_ident($1) where quote_ident($1).id=1)...
                                                             ^

********** Error **********

ERROR: syntax error at or near "."

และนี่คือข้อผิดพลาดที่ฉันได้รับเมื่อเปลี่ยนเป็นสิ่งนี้select * from quote_ident($1) tab where tab.id=1:

ERROR:  column tab.id does not exist
LINE 1: ...T EXISTS (select * from quote_ident($1) tab where tab.id...

อาจใช้quote_ident($1)งานได้เพราะไม่มีwhere quote_ident($1).id=1ส่วนที่ฉันได้รับ1ซึ่งหมายความว่ามีการเลือกบางอย่าง ทำไมquote_ident($1)งานชิ้นแรกและงานที่สองถึงไม่พร้อมกัน? และจะแก้ไขได้อย่างไร?


ฉันรู้ว่าคำถามนี้ค่อนข้างเก่า แต่ฉันพบคำถามนี้ในขณะที่ค้นหาคำตอบของปัญหาอื่น ฟังก์ชั่นของคุณไม่สามารถค้นหาข้อมูล _schema ได้หรือไม่? ฉันหมายความว่านั่นคือสิ่งที่มีไว้เพื่อให้คุณสอบถามและดูว่ามีวัตถุอะไรอยู่ในฐานข้อมูล เพียงแค่ความคิด
David S

@DavidS ขอบคุณสำหรับความคิดเห็นฉันจะลองดู
John Doe

คำตอบ:


126

สิ่งนี้สามารถทำให้ง่ายขึ้นและปรับปรุงเพิ่มเติม:

CREATE OR REPLACE FUNCTION some_f(_tbl regclass, OUT result integer)
    LANGUAGE plpgsql AS
$func$
BEGIN
   EXECUTE format('SELECT (EXISTS (SELECT FROM %s WHERE id = 1))::int', _tbl)
   INTO result;
END
$func$;

โทรด้วยชื่อที่ตรงตามข้อกำหนดของสคีมา (ดูด้านล่าง):

SELECT some_f('myschema.mytable');  -- would fail with quote_ident()

หรือ:

SELECT some_f('"my very uncommon table name"');

ประเด็นสำคัญ

  • ใช้OUTพารามิเตอร์เพื่อลดความซับซ้อนของฟังก์ชัน คุณสามารถเลือกผลลัพธ์ของไดนามิก SQL ได้โดยตรงและทำได้ ไม่จำเป็นต้องมีตัวแปรและโค้ดเพิ่มเติม

  • EXISTSทำในสิ่งที่คุณต้องการ คุณจะได้รับtrueถ้าแถวนั้นมีอยู่หรือfalseอย่างอื่น มีหลายวิธีในการดำเนินการนี้EXISTSโดยทั่วไปจะมีประสิทธิภาพมากที่สุด

  • ดูเหมือนคุณจะต้องการจำนวนเต็มคืนดังนั้นฉันจึงโยนbooleanผลลัพธ์จากEXISTSถึงไปintegerซึ่งให้ผลลัพธ์ตามที่คุณมี ฉันจะส่งคืนบูลีนแทน

  • ฉันใช้ประเภทตัวระบุวัตถุregclassเป็นประเภทอินพุตสำหรับ_tbl. ที่ทำทุกอย่างquote_ident(_tbl)หรือformat('%I', _tbl)จะทำ แต่ดีกว่าเพราะ:

  • .. มันป้องกันการฉีด SQLเช่นกัน

  • .. มันล้มเหลวทันทีและอย่างงดงามยิ่งขึ้นหากชื่อตารางไม่ถูกต้อง / ไม่มีอยู่จริง / ผู้ใช้ปัจจุบันมองไม่เห็น ( regclassพารามิเตอร์ใช้ได้เฉพาะกับตารางที่มีอยู่ )

  • .. ใช้งานได้กับชื่อตารางที่มีคุณสมบัติของสคีมาโดยที่ธรรมดาquote_ident(_tbl)หรือformat(%I)จะล้มเหลวเนื่องจากไม่สามารถแก้ไขความคลุมเครือ คุณจะต้องผ่านและหลีกเลี่ยงสคีมาและชื่อตารางแยกกัน

  • ฉันยังคงใช้อยู่format()เพราะมันทำให้ไวยากรณ์ง่ายขึ้น (และเพื่อแสดงให้เห็นว่ามันใช้อย่างไร) แต่ใช้%sแทน%I. โดยปกติการสืบค้นข้อมูลจะซับซ้อนกว่าจึงformat()ช่วยได้มากขึ้น สำหรับตัวอย่างง่ายๆที่เราสามารถเชื่อมต่อกันได้:

      EXECUTE 'SELECT (EXISTS (SELECT FROM ' || _tbl || ' WHERE id = 1))::int'
    
  • ไม่จำเป็นต้องกำหนดคุณสมบัติของidคอลัมน์ในขณะที่มีเพียงตารางเดียวในFROMรายการ ตัวอย่างนี้ไม่มีความคลุมเครือ (แบบไดนามิก) คำสั่ง SQL ภายในEXECUTEมีขอบเขตแยกต่างหากไม่สามารถมองเห็นตัวแปรของฟังก์ชันหรือพารามิเตอร์ได้ซึ่งตรงข้ามกับคำสั่ง SQL ธรรมดาในเนื้อหาของฟังก์ชัน

นี่เป็นเหตุผลที่คุณมักจะหลบหนีการป้อนข้อมูลของผู้ใช้สำหรับ SQL แบบไดนามิกอย่างถูกต้อง:

db <> fiddle ที่นี่สาธิตการฉีด SQL
Old sqlfiddle


2
@suhprano: แน่นอน ลองดู:DO $$BEGIN EXECUTE 'ANALYZE mytbl'; END$$;
Erwin Brandstetter

ทำไม% s ถึงไม่ใช่% L?
โลตัส

3
@ โลตัส: คำอธิบายอยู่ในคำตอบ regclassค่าจะถูกหลีกเลี่ยงโดยอัตโนมัติเมื่อส่งออกเป็นข้อความ %Lจะผิดในกรณีนี้
Erwin Brandstetter

CREATE OR REPLACE FUNCTION table_rows(_tbl regclass, OUT result integer) AS $func$ BEGIN EXECUTE 'SELECT (SELECT count(1) FROM ' || _tbl || ' )::int' INTO result; END $func$ LANGUAGE plpgsql; สร้างฟังก์ชันการนับแถวตารางselect table_rows('nf_part1');
Ferris

เราจะรับคอลัมน์ทั้งหมดได้อย่างไร
Ashish

13

ถ้าเป็นไปได้อย่าทำอย่างนี้

นั่นคือคำตอบ - เป็นการต่อต้านรูปแบบ หากลูกค้าทราบตารางที่ต้องการข้อมูลจากนั้นSELECT FROM ThatTableหากลูกค้ารู้ว่าโต๊ะมันต้องการข้อมูลจากแล้วหากฐานข้อมูลได้รับการออกแบบในลักษณะที่จำเป็นดูเหมือนว่าจะได้รับการออกแบบให้เหมาะสมย่อย หากชั้นการเข้าถึงข้อมูลต้องการทราบว่ามีค่าอยู่ในตารางหรือไม่การเขียน SQL ในโค้ดนั้นทำได้ง่ายและการผลักโค้ดนี้ลงในฐานข้อมูลก็ไม่ดี

สำหรับฉันแล้วดูเหมือนว่าการติดตั้งอุปกรณ์ภายในลิฟต์ซึ่งเราสามารถพิมพ์หมายเลขชั้นที่ต้องการได้ หลังจากกดปุ่ม Go แล้วจะเลื่อนมือกลไปยังปุ่มที่ถูกต้องสำหรับชั้นที่ต้องการแล้วกด สิ่งนี้แนะนำปัญหาที่อาจเกิดขึ้นมากมาย

โปรดทราบ: ที่นี่ไม่มีเจตนาล้อเลียน ตัวอย่างลิฟต์โง่ ๆ ของฉันคือ * อุปกรณ์ที่ดีที่สุดที่ฉันสามารถจินตนาการได้ * เพื่อชี้ให้เห็นปัญหาเกี่ยวกับเทคนิคนี้อย่างรวบรัด มันเพิ่มเลเยอร์ของทิศทางที่ไร้ประโยชน์ย้ายตัวเลือกชื่อตารางจากพื้นที่ผู้โทร (โดยใช้ DSL, SQL ที่แข็งแกร่งและเข้าใจดี) ลงในไฮบริดโดยใช้โค้ด SQL ฝั่งเซิร์ฟเวอร์ที่คลุมเครือ / แปลกประหลาด

การแบ่งความรับผิดชอบดังกล่าวผ่านการเคลื่อนย้ายตรรกะการสร้างแบบสอบถามไปยัง SQL แบบไดนามิกทำให้โค้ดเข้าใจยากขึ้น มันละเมิดแบบแผนมาตรฐานและเชื่อถือได้ (วิธีที่แบบสอบถาม SQL เลือกสิ่งที่จะเลือก) ในชื่อของโค้ดที่กำหนดเองที่เต็มไปด้วยข้อผิดพลาด

ต่อไปนี้เป็นประเด็นโดยละเอียดเกี่ยวกับปัญหาที่อาจเกิดขึ้นกับแนวทางนี้:

  • Dynamic SQL นำเสนอความเป็นไปได้ของการแทรก SQL ที่ยากที่จะจดจำในโค้ดส่วนหน้าหรือโค้ดส่วนหลังเพียงอย่างเดียว (ต้องตรวจสอบร่วมกันเพื่อดูสิ่งนี้)

  • โพรซีเดอร์และฟังก์ชันที่จัดเก็บไว้สามารถเข้าถึงทรัพยากรที่เจ้าของ SP / ฟังก์ชันมีสิทธิ์ แต่ผู้เรียกใช้ไม่ได้ เท่าที่ฉันเข้าใจโดยไม่ต้องดูแลเป็นพิเศษตามค่าเริ่มต้นเมื่อคุณใช้โค้ดที่สร้างไดนามิก SQL และเรียกใช้ฐานข้อมูลจะเรียกใช้ไดนามิก SQL ภายใต้สิทธิ์ของผู้โทร ซึ่งหมายความว่าคุณจะไม่สามารถใช้ออบเจ็กต์ที่มีสิทธิพิเศษได้เลยหรือคุณต้องเปิดให้กับไคลเอนต์ทั้งหมดเพื่อเพิ่มพื้นที่ผิวของการโจมตีที่อาจเกิดขึ้นกับข้อมูลที่มีสิทธิ์ การตั้งค่า SP / ฟังก์ชันในขณะสร้างเพื่อให้ทำงานเป็นผู้ใช้เฉพาะ (ใน SQL Server EXECUTE AS) อาจช่วยแก้ปัญหานั้นได้ แต่ทำให้สิ่งต่างๆซับซ้อนมากขึ้น สิ่งนี้ทำให้ความเสี่ยงของการฉีด SQL ที่กล่าวถึงในประเด็นก่อนหน้านี้ทวีความรุนแรงยิ่งขึ้นโดยการทำให้ไดนามิก SQL เป็นเวกเตอร์การโจมตีที่น่าดึงดูดมาก

  • เมื่อนักพัฒนาต้องเข้าใจว่าโค้ดของแอปพลิเคชันกำลังทำอะไรเพื่อแก้ไขหรือแก้ไขข้อบกพร่องเขาจะพบว่าการเรียกใช้การสืบค้น SQL ที่ถูกต้องเป็นเรื่องยากมาก สามารถใช้ SQL profiler ได้ แต่สิ่งนี้ต้องใช้สิทธิพิเศษและอาจมีผลเสียต่อระบบการผลิต การสืบค้นที่ดำเนินการสามารถบันทึกได้โดย SP แต่จะเพิ่มความซับซ้อนเพื่อประโยชน์ที่น่าสงสัย (ต้องรองรับตารางใหม่การล้างข้อมูลเก่า ฯลฯ ) และค่อนข้างไม่ชัดเจน ในความเป็นจริงแอปพลิเคชั่นบางตัวได้รับการออกแบบมาเพื่อให้นักพัฒนาไม่มีข้อมูลรับรองฐานข้อมูลดังนั้นจึงแทบเป็นไปไม่ได้เลยที่เขาจะเห็นข้อความค้นหาที่ถูกส่งไป

  • เมื่อเกิดข้อผิดพลาดเช่นเมื่อคุณพยายามเลือกตารางที่ไม่มีอยู่คุณจะได้รับข้อความตามบรรทัด "ชื่อวัตถุที่ไม่ถูกต้อง" จากฐานข้อมูล สิ่งนี้จะเกิดขึ้นเหมือนกันทุกประการไม่ว่าคุณจะเขียน SQL ในส่วนหลังหรือฐานข้อมูล แต่ความแตกต่างก็คือนักพัฒนาที่ไม่ดีบางคนที่พยายามแก้ไขปัญหาระบบจะต้องสะกดลึกลงไปอีกระดับหนึ่งในอีกถ้ำหนึ่งที่อยู่ด้านล่างซึ่ง มีปัญหาอยู่เพื่อเจาะลึกขั้นตอนที่น่าแปลกใจที่ไม่ต้องพยายามหาว่าปัญหาคืออะไร บันทึกจะไม่แสดง "ข้อผิดพลาดใน GetWidget" แต่จะแสดง "ข้อผิดพลาดใน OneProcedureToRuleThemAllRunner" นามธรรมนี้โดยทั่วไปจะทำให้ระบบที่เลวร้ายยิ่ง

ตัวอย่างใน pseudo-C # ของการสลับชื่อตารางตามพารามิเตอร์:

string sql = $"SELECT * FROM {EscapeSqlIdentifier(tableName)};"
results = connection.Execute(sql);

แม้ว่าสิ่งนี้จะไม่สามารถขจัดปัญหาที่เป็นไปได้ทั้งหมดเท่าที่จะเป็นไปได้ แต่ข้อบกพร่องที่ฉันระบุไว้กับเทคนิคอื่น ๆ จะไม่มีอยู่ในตัวอย่างนี้


4
ฉันไม่เห็นด้วยอย่างยิ่งกับเรื่องนี้ สมมติว่าคุณกดปุ่ม "ไป" นี้จากนั้นกลไกบางอย่างจะตรวจสอบว่าพื้นนั้นมีอยู่จริงหรือไม่ อาจใช้ฟังก์ชันในทริกเกอร์ซึ่งสามารถตรวจสอบเงื่อนไขบางประการได้ ความปรารถนานี้อาจไม่ใช่สิ่งที่สวยงามที่สุด แต่ถ้าระบบมีขนาดใหญ่พออยู่แล้วและคุณต้องทำการแก้ไขบางอย่างด้วยตรรกะของมันตัวเลือกนี้ไม่ได้น่าทึ่งมากนักฉันคิดว่า
John Doe

2
แต่ให้พิจารณาว่าการพยายามกดปุ่มที่ไม่มีอยู่จะทำให้เกิดข้อยกเว้นไม่ว่าคุณจะจัดการอย่างไร คุณไม่สามารถกดปุ่มที่ไม่มีอยู่จริงได้ดังนั้นจึงไม่มีประโยชน์ในการเพิ่มเลเยอร์เพื่อตรวจสอบตัวเลขที่ไม่มีอยู่จริงเนื่องจากไม่มีการป้อนหมายเลขดังกล่าวก่อนที่คุณจะสร้างเลเยอร์ดังกล่าว! ในความคิดของฉัน Abstraction เป็นเครื่องมือที่ทรงพลังที่สุดในการเขียนโปรแกรม อย่างไรก็ตามการเพิ่มชั้นที่เพียงไม่ดีซ้ำเป็นนามธรรมที่มีอยู่เป็นที่ไม่ถูกต้อง ฐานข้อมูลที่ตัวเองเป็นอยู่แล้วชั้น abstraction ที่แมปชื่อชุดข้อมูล
ErikE

3
จับได้เห็นชัดตรงเผง. จุดรวมของ SQL คือการแสดงชุดข้อมูลที่คุณต้องการแยกออกมา สิ่งเดียวที่ฟังก์ชันนี้ทำคือการห่อหุ้มคำสั่ง SQL แบบ "กระป๋อง" เนื่องจากข้อเท็จจริงที่ว่าตัวระบุนั้นได้รับการเข้ารหัสอย่างหนักทำให้สิ่งทั้งหมดมีกลิ่นเหม็น
Nick Hristov

2
@three จนกว่าจะมีคนอยู่ในช่วงความเชี่ยวชาญ (ดูแบบจำลองการได้มาซึ่งทักษะของเดรย์ฟัส ) ของทักษะเขาก็ควรปฏิบัติตามกฎอย่าง "อย่าส่งชื่อตารางไปยังขั้นตอนที่จะใช้ใน SQL แบบไดนามิก" แม้เค้าว่ามันเป็นไปไม่ได้เสมอไม่ดีคือเป็นตัวเองคำแนะนำดี รู้แบบนี้แล้วมือใหม่จะติดใจเอาไปใช้! เลวร้าย. เฉพาะผู้เชี่ยวชาญของหัวข้อเท่านั้นที่ควรทำผิดกฎเนื่องจากเป็นเพียงคนเดียวที่มีประสบการณ์ที่จะรู้ว่าการละเมิดกฎดังกล่าวสมเหตุสมผลหรือไม่
ErikE

2
@ สามถ้วยฉันอัปเดตพร้อมรายละเอียดเพิ่มเติมว่าทำไมถึงเป็นความคิดที่ไม่ดี
ErikE

10

ภายในโค้ด plpgsql ต้องใช้คำสั่งEXECUTEสำหรับเคียวรีที่ชื่อตารางหรือคอลัมน์มาจากตัวแปร นอกจากนี้ยังIF EXISTS (<query>)ไม่อนุญาตให้ก่อสร้างเมื่อqueryสร้างแบบไดนามิก

นี่คือฟังก์ชั่นของคุณที่แก้ไขปัญหาทั้งสองอย่าง:

CREATE OR REPLACE FUNCTION some_f(param character varying) RETURNS integer 
AS $$
DECLARE
 v int;
BEGIN
      EXECUTE 'select 1 FROM ' || quote_ident(param) || ' WHERE '
            || quote_ident(param) || '.id = 1' INTO v;
      IF v THEN return 1; ELSE return 0; END IF;
END;
$$ LANGUAGE plpgsql;

ขอบคุณฉันทำแบบเดียวกันเมื่อสองสามนาทีก่อนเมื่ออ่านคำตอบของคุณ ข้อแตกต่างเพียงอย่างเดียวคือฉันต้องลบออกquote_ident()เพราะมันเพิ่มเครื่องหมายคำพูดพิเศษซึ่งทำให้ฉันประหลาดใจเล็กน้อยเพราะมันถูกใช้ในตัวอย่างส่วนใหญ่
John Doe

จำเป็นต้องใช้เครื่องหมายคำพูดพิเศษเหล่านี้ถ้า / เมื่อชื่อตารางมีอักขระภายนอก [az] หรือถ้า / เมื่อมันขัดแย้งกับตัวระบุที่สงวนไว้ (ตัวอย่าง: "group" เป็นชื่อตาราง)
Daniel Vérité

และโปรดระบุลิงก์ที่พิสูจน์ได้ว่าIF EXISTS <query>โครงสร้างไม่มีอยู่จริงหรือไม่ ฉันค่อนข้างมั่นใจว่าฉันเห็นอะไรแบบนั้นเป็นตัวอย่างโค้ดที่ใช้งานได้
John Doe

1
@JohnDoe: IF EXISTS (<query>) THEN ...เป็นโครงสร้างที่ถูกต้องสมบูรณ์ใน plpgsql ไม่ใช่ด้วยไดนามิก SQL สำหรับ<query>. ฉันใช้มันมาก นอกจากนี้ฟังก์ชันนี้ยังสามารถปรับปรุงได้เล็กน้อย ฉันโพสต์คำตอบ
Erwin Brandstetter

1
ขออภัยคุณพูดถูกif exists(<query>)มันใช้ได้ในกรณีทั่วไป เพิ่งตรวจสอบและแก้ไขคำตอบตามนั้น
Daniel Vérité

4

อย่างแรกไม่ได้ "ทำงาน" จริงในความหมายที่คุณหมายถึงมันใช้ได้เฉพาะในกรณีที่ไม่ก่อให้เกิดข้อผิดพลาด

ลองSELECT * FROM quote_ident('table_that_does_not_exist');แล้วคุณจะเห็นว่าเหตุใดฟังก์ชันของคุณจึงส่งคืน 1: การเลือกกำลังส่งคืนตารางที่มีหนึ่งคอลัมน์ (ชื่อquote_ident) โดยมีแถวเดียว (ตัวแปร$1หรือในกรณีนี้โดยเฉพาะtable_that_does_not_exist)

สิ่งที่คุณต้องการทำจะต้องใช้ SQL แบบไดนามิกซึ่งเป็นสถานที่ที่มีการใช้quote_*ฟังก์ชันต่างๆ


ขอบคุณมาก Matt table_that_does_not_existให้ผลลัพธ์แบบเดียวกันคุณพูดถูก
John Doe

2

หากคำถามคือการทดสอบว่าตารางว่างหรือไม่ (id = 1) นี่คือ proc ที่เก็บไว้ของ Erwin รุ่นที่เรียบง่าย:

CREATE OR REPLACE FUNCTION isEmpty(tableName text, OUT zeroIfEmpty integer) AS
$func$
BEGIN
EXECUTE format('SELECT COALESCE ((SELECT 1 FROM %s LIMIT 1),0)', tableName)
INTO zeroIfEmpty;
END
$func$ LANGUAGE plpgsql;

1

ฉันรู้ว่านี่เป็นเธรดเก่า แต่เมื่อเร็ว ๆ นี้ฉันได้พบกับมันเมื่อพยายามแก้ปัญหาเดียวกัน - ในกรณีของฉันสำหรับสคริปต์ที่ค่อนข้างซับซ้อน

การเปลี่ยนสคริปต์ทั้งหมดให้เป็นไดนามิก SQL นั้นไม่เหมาะอย่างยิ่ง เป็นงานที่น่าเบื่อและเกิดข้อผิดพลาดได้ง่ายและคุณสูญเสียความสามารถในการกำหนดพารามิเตอร์: พารามิเตอร์จะต้องถูกสอดแทรกเป็นค่าคงที่ใน SQL ซึ่งมีผลเสียต่อประสิทธิภาพและความปลอดภัย

ต่อไปนี้เป็นเคล็ดลับง่ายๆที่ช่วยให้คุณคงสภาพ SQL ไว้ได้หากคุณต้องการเลือกจากตารางของคุณเท่านั้น - ใช้ไดนามิก SQL เพื่อสร้างมุมมองชั่วคราว:

CREATE OR REPLACE FUNCTION some_f(_tbl varchar) returns integer
AS $$
BEGIN
    drop view if exists myview;
    execute format('create temporary view myview as select * from %s', _tbl);
    -- now you can reference myview in the SQL
    IF EXISTS (select * from myview where myview.id=1) THEN
     return 1;
    END IF;
    return 0;
END;
$$ language plpgsql;

0

หากคุณต้องการให้ชื่อตารางชื่อคอลัมน์และค่าถูกส่งแบบไดนามิกไปยังฟังก์ชันเป็นพารามิเตอร์

ใช้รหัสนี้

create or replace function total_rows(tbl_name text, column_name text, value int)
returns integer as $total$
declare
total integer;
begin
    EXECUTE format('select count(*) from %s WHERE %s = %s', tbl_name, column_name, value) INTO total;
    return total;
end;
$total$ language plpgsql;


postgres=# select total_rows('tbl_name','column_name',2); --2 is the value

-2

ฉันมี PostgreSQL เวอร์ชัน 9.4 และฉันมักจะใช้รหัสนี้:

CREATE FUNCTION add_new_table(text) RETURNS void AS
$BODY$
begin
    execute
        'CREATE TABLE ' || $1 || '(
        item_1      type,
        item_2      type
        )';
end;
$BODY$
LANGUAGE plpgsql

แล้ว:

SELECT add_new_table('my_table_name');

มันทำงานได้ดีสำหรับฉัน

โปรดทราบ! ตัวอย่างด้านบนคือหนึ่งในตัวอย่างที่แสดง "จะทำอย่างไรถ้าเราต้องการรักษาความปลอดภัยระหว่างการสืบค้นฐานข้อมูล": P


1
การสร้างnewตารางจะแตกต่างจากการดำเนินการโดยใช้ชื่อของตารางที่มีอยู่ ไม่ว่าจะด้วยวิธีใดคุณควรหลีกเลี่ยงพารามิเตอร์ข้อความที่ดำเนินการเป็นรหัสหรือคุณเปิดให้ SQL injection
Erwin Brandstetter

โอ้ใช่ความผิดพลาดของฉัน หัวข้อนี้ทำให้ฉันเข้าใจผิดและนอกจากนี้ฉันไม่ได้อ่านจนจบ ปกติในกรณีของฉัน : P เหตุใดโค้ดที่มีพารามิเตอร์ข้อความจึงถูกแทรก
dm3

อ๊ะมันอันตรายจริงๆ ขอบคุณสำหรับคำตอบ!
dm3
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.