Bạn phải bảo vệ chống lại chèn SQL bất cứ khi nào bạn chuyển đầu vào của người dùng thành mã. Điều đó bao gồm tên bảng và cột đến từ danh mục hệ thống hoặc từ thông tin nhập trực tiếp của người dùng. Bằng cách này, bạn cũng ngăn ngừa các trường hợp ngoại lệ nhỏ với các số nhận dạng không chuẩn. Về cơ bản có ba các phương thức tích hợp:
1. format()
Truy vấn đầu tiên, được làm sạch:
CREATE OR REPLACE FUNCTION foo(_t text)
RETURNS void
LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE format('
ALTER TABLE %I ADD COLUMN c1 varchar(20)
, ADD COLUMN c2 varchar(20)', _t);
END
$func$;
format()
yêu cầu Postgres 9.1 trở lên. Sử dụng nó với %I
định dạng.
Riêng tên bảng có thể không rõ ràng. Bạn có thể phải cung cấp tên lược đồ để tránh tình cờ thay đổi bảng sai. Có liên quan:
- CHÈN với tên bảng động trong chức năng kích hoạt
- Cách search_path ảnh hưởng đến độ phân giải của mã định danh và "giản đồ hiện tại"
Ngoài ra:thêm nhiều cột với một ALTER TABLE
lệnh rẻ hơn.
2. regclass
Bạn cũng có thể sử dụng truyền cho một lớp đã đăng ký (regclass
) đối với trường hợp đặc biệt của hiện có tên bảng. Tùy chọn đủ điều kiện giản đồ. Điều này không thành công ngay lập tức và duyên dáng đối với các tên bảng không hợp lệ và hiển thị cho người dùng đang gọi. Truy vấn đầu tiên được làm sạch bằng cách truyền thành regclass
:
CREATE OR REPLACE FUNCTION foo(_t regclass)
RETURNS void
LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE 'ALTER TABLE ' || _t || ' ADD COLUMN c1 varchar(20)
, ADD COLUMN c2 varchar(20)';
END
$func$;
Gọi:
SELECT foo('table_name');
Hoặc:
SELECT foo('my_schema.table_name'::regclass);
Ngoài ra:hãy xem xét chỉ sử dụng text
thay vì varchar(20)
.
3. quote_ident()
Truy vấn thứ 2 đã được khử trùng:
CREATE OR REPLACE FUNCTION foo(_t regclass, _c text)
RETURNS void
LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE 'UPDATE ' || _t -- sanitized with regclass
|| ' SET ' || quote_ident(_c) || ' = ''This is a test''';
END
$func$;
Đối với nhiều phép nối / nội suy, format()
sạch hơn ...
Các câu trả lời liên quan:
- Tên bảng dưới dạng tham số hàm PostgreSQL
- Các hàm postgres so với các truy vấn đã chuẩn bị trước
Phân biệt chữ hoa chữ thường!
Lưu ý rằng các số nhận dạng không được trích dẫn là không đúc thành chữ thường ở đây. Khi được sử dụng làm định danh trong SQL [Postgres tự động chuyển thành chữ thường] [7]. Nhưng ở đây chúng tôi vượt qua chuỗi cho SQL động. Khi được thoát như đã trình bày, các số nhận dạng CaMel-case (như UserS
) sẽ được giữ nguyên bằng cách trích dẫn kép ("UserS"
), giống như các tên không chuẩn khác như "name with space"
"SELECT"
v.v ... Do đó, tên có phân biệt chữ hoa chữ thường trong ngữ cảnh này.
Lời khuyên thường xuyên của tôi là chỉ sử dụng các số nhận dạng chữ thường hợp pháp và đừng bao giờ lo lắng về điều đó.
Ngoài ra:dấu ngoặc kép dành cho các giá trị, dấu ngoặc kép dành cho số nhận dạng. Xem:
- https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS