2009-02-04 39 views
18

Có cách nào tiêu chuẩn để ràng buộc mảng (của vô hướng) trong truy vấn SQL không? Tôi muốn để ràng buộc vào một điều khoản IN, như vậy:Có ràng buộc tham số SQL cho mảng không?

SELECT * FROM junk WHERE junk.id IN (?); 

tôi tình cờ được sử dụng Perl::DBI mà cưỡng ép tham số để vô hướng, vì vậy tôi kết thúc với truy vấn vô dụng như:

SELECT * FROM junk WHERE junk.id IN ('ARRAY(0xdeadbeef)'); 

Làm rõ: Tôi đặt truy vấn trong tệp .sql của riêng nó, vì vậy chuỗi đã được tạo thành. Trường hợp các câu trả lời đề cập đến việc tạo chuỗi truy vấn động thì tôi có thể thực hiện tìm kiếm và thay thế.

Chỉnh sửa: Câu hỏi này trùng lặp với Parameterizing a SQL IN clause?. Ban đầu tôi nghĩ rằng nó nên được đóng cửa như vậy, nhưng nó có vẻ như nó tích lũy một số thông tin cụ thể Perl tốt.

+0

Đây là một dupe của một câu hỏi nổi tiếng. Hãy để tôi chỉ tìm thấy nó .... – Ray

+0

Nó cũng là cơ sở dữ liệu cụ thể ... –

+0

Cool - tìm kiếm, nhưng không thể tìm thấy nó bản thân mình. – cdleary

Trả lời

12

Bạn chỉ rõ "đây là câu lệnh SQL cho một truy vấn có một tham số" - điều đó sẽ không hoạt động khi bạn muốn có nhiều tham số. Đó là một nỗi đau để đối phó với, tất nhiên. Hai biến thể khác với những gì đã được đề xuất:

1) Sử dụng DBI-> trích dẫn thay cho người giữ chỗ.

my $sql = "select foo from bar where baz in (" 
      . join(",", map { $dbh->quote($_) } @bazs) 
      . ")"; 
my $data = $dbh->selectall_arrayref($sql); 

2) Sử dụng ORM để thực hiện loại công cụ cấp thấp này cho bạn. Ví dụ: DBIx :: Class or Rose :: DB :: Object.

+1

tuy nhiên, ở bên cạnh tôi, sử dụng DBI-> quote không hoạt động; tôi đã sử dụng $ dbh-> quote; ở đây $ dbh là từ $ dbh = DBI-> connect ("DBI: mysql: $ db: $ host", $ user, $ pass); – hetaoblog

+0

@hetablog Thật vậy, bạn đã đúng. Tôi đã cập nhật câu trả lời. –

2

Trong python, tôi đã luôn luôn kết thúc lên làm một cái gì đó như: '?'

query = 'select * from junk where junk.id in (' 
for id in junkids: 
    query = query + '?,' 
query = query + ')' 

cursor.execute(query, junkids) 

... trong đó chủ yếu xây dựng một truy vấn với một cho từng phần tử trong danh sách.

(và nếu có các thông số khác trong đó quá, bạn cần phải chắc chắn rằng bạn xếp hàng thứ lên một cách chính xác khi bạn thực hiện truy vấn)

[chỉnh sửa để làm cho mã dễ hiểu cho những người không python. Có một lỗi, nơi mà các truy vấn sẽ có thừa một dấu phẩy sau khi người cuối cùng, mà tôi sẽ để lại trong vì sửa chữa nó sẽ chỉ đám mây ý tưởng chung]

+0

Chắc chắn, nếu bạn không lo lắng về SQL Injection thì bạn không cần tham số nào cả. – Ray

+1

@Ray: Tôi không hiểu nhận xét của bạn - anh * là * làm tham số ràng buộc, chỉ cần thêm số lượng tham số thích hợp để liên kết động. – cdleary

+0

hm .. vậy là anh ấy. Xin lỗi, là lỗi của tôi. – Ray

9

tôi làm điều gì đó như:

my $dbh = DBI->connect(...); 
my @vals= (1,2,3,4,5); 
my $sql = 'SELECT * FROM table WHERE id IN (' . join(',', map { '?' } @vals) . ')'; 
my $sth = $dbh->prepare($sql); 
$sth->execute(@vals); 
+0

Nhưng hãy nhớ tự bảo vệ mình khỏi các cuộc tấn công SQL Injection ... – MatBailie

+3

@ Dems, ví dụ của JDrago đã sử dụng các biến liên kết, vì vậy anh ta không cần phải làm gì khác để ngăn chặn việc tiêm SQL. – mpeters

+1

'map {'?' } @ vals' là đơn giản hơn '('?') x @ vals' – ysth

4

Với đồng bằng DBI bạn sẽ phải tự xây dựng SQL, như được đề xuất ở trên. DBIx::Simple (trình bao bọc cho DBI) thực hiện việc này cho bạn tự động bằng cách sử dụng '??' ký hiệu:

$db->query("select * from foo where bar in (??)", @values); 
+0

Nhưng sau đó bạn có thể ràng buộc các tham số ở nơi khác trong SQL không? Tôi không thấy làm thế nào bạn có thể ràng buộc các thông số sau khi ?? trừ khi nó tùy ý lấy tham chiếu mảng thay thế. – cdleary

+0

Câu hỏi hay. Nếu tôi hiểu tài liệu chính xác, bạn có thể có nhiều trình giữ chỗ đơn lẻ hoặc một ký tự '??', chứ không phải cả hai. – 8jean

13

Nếu bạn không thích bản đồ đó, bạn có thể sử dụng 'x' điều hành: '?'

my $params = join ', ' => ('?') x @foo; 
my $sql = "SELECT * FROM table WHERE id IN ($params)"; 
my $sth = $dbh->prepare($sql); 
$sth->execute(@foo); 

Các dấu ngoặc đơn là cần thiết xung quanh bởi vì lực đó 'x' nằm trong ngữ cảnh danh sách.

Đọc "perldoc perlop" và tìm kiếm 'Binary "x"' để biết thêm thông tin (trong phần "Operlic Operators").

+0

đây phải là câu trả lời đúng (ít nhất theo ý kiến ​​của tôi). – maletin

+0

Từ đâu đến từ đâu? Bạn có nghĩa là @foo? – teambob

+0

teambob: vâng, ý tôi là @foo. Tôi đã thay đổi nó. Cảm ơn! – Ovid

0

Tôi sử dụng DBIx::DWIW. Nó chứa một hàm gọi là InList(). Điều này sẽ tạo ra một phần của SQL cần thiết cho danh sách.Tuy nhiên điều này chỉ hoạt động nếu bạn có tất cả các SQL của bạn trong chương trình thay vì bên ngoài trong một tập tin riêng biệt.

6

Và thêm một cách để xây dựng SQL là sử dụng cái gì đó như SQL::Abstract ....

+0

Tôi vừa mới đăng bài này, và tôi chắc chắn nghĩ đó là "câu trả lời đúng". Nếu bạn không thể sử dụng ORM, ít nhất hãy sử dụng một cái gì đó như SQL :: Abstract (hoặc có thể là Fey). – jrockway

0

Sử dụng

SELECT * FROM junk WHERE junk.id = ANY (?); 

thay

Các vấn đề liên quan