2013-03-24 22 views
5

Trong khi kiểm tra ra PostgreSQL's md5() function tôi nhận thấy hành vi rất kỳ lạ:md5() làm việc với nghĩa đen, nhưng không phải với dữ liệu cột

trình như mong đợi

SELECT md5('abc') 
--"900150983cd24fb0d6963f7d28e17f72" 

Nhưng sử dụng md5() chức năng trong một truy vấn:

SELECT request_id, md5(request_id) 
FROM Request 
ORDER BY request_id 

kết quả trong lỗi này:

ERROR: function md5(integer) does not exist 
LINE 1: SELECT request_id, md5(request_id) 
         ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. 

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

ERROR: function md5(integer) does not exist 
SQL state: 42883 
Hint: No function matches the given name and argument types. You might need to add explicit type casts. 
Character: 20 

Cách chức năng không tồn tại nếu nó hoạt động trong truy vấn đầu tiên? Tôi đang làm gì sai; cách chính xác để sử dụng md5() trong truy vấn SELECT là gì?

+2

Điều đó dường như không kỳ quái chút nào. Trong truy vấn đầu tiên, bạn đã chuyển văn bản, trong khi trong lần truy vấn thứ hai bạn đang cố chuyển số nguyên. – us2012

+0

@ us2012: yup, đó là sự khác biệt. –

+0

Nói chung nó không có ý nghĩa nhiều để lấy md5 của một số nguyên, vì vậy tôi muốn được quan tâm đến lý do tại sao bạn đang cố gắng để làm điều này. –

Trả lời

10

Hàm mong đợi văn bản dưới dạng tham số. Cast nó:

SELECT request_id, md5(request_id::text) 
FROM Request 
ORDER BY request_id 

Một hàm có tên md5 chấp nhận một tham số số nguyên không tồn tại nhưng bạn có thể tạo ra nó:

create function md5(integer) 
returns text as $$ 

select md5($1::text); 

$$ language sql immutable; 

Sau đó, sẽ có 3 chữ ký cho md5:

=> \df md5 
          List of functions 
    Schema | Name | Result data type | Argument data types | Type 
------------+------+------------------+---------------------+-------- 
pg_catalog | md5 | text    | bytea    | normal 
pg_catalog | md5 | text    | text    | normal 
public  | md5 | text    | integer    | normal 

Như đã chỉ ra trong các chú thích cho câu trả lời này hàm băm md5 của biểu diễn văn bản của số nguyên có thể không phải là những gì bạn muốn. Để có hash của nhị phân chữ ký md5 chấp nhận một tham số bytea nên được sử dụng:

select md5(('\x' || right('0000000' || to_hex(200), 8))::bytea); 
       md5     
---------------------------------- 
b7b436d004c1cc0501bee9e296d2eaa4 

Và thay thế các chức năng tạo ra trước đó:

create or replace function md5(integer) 
returns text as $$ 

select md5(('\x' || right('0000000' || to_hex($1), 8))::bytea); 

$$ language sql immutable; 
+0

Câu chuyện có thật. Tôi đã tìm ra ngay sau khi tôi đăng câu hỏi. Cảm ơn Clodoaldo. –

+2

Lưu ý rằng việc truyền số nguyên thành văn bản có nghĩa là bạn đang dùng md5 của biểu diễn * văn bản của số nguyên *. Điều này có thể không phải là những gì bạn có ý định khi giao tiếp với các hệ thống khác. Nếu bạn thực sự muốn lấy md5 của biểu diễn nhị phân của số nguyên, bạn sẽ cần sử dụng ngôn ngữ thủ tục như pl/perl, pl/python, vv để lấy md5 của biểu diễn nhị phân thích hợp (ký 32 bit chút cuối, cho thí dụ). –

+1

@Craig Điểm tốt. Nhưng có vẻ như một ngôn ngữ thủ tục là không cần thiết. Hay tôi đang thiếu một cái gì đó? –

0

Lỗi này là một chút sai lệch; chức năng md5() tồn tại, không phải để làm việc trên số nguyên. Sử dụng một nhúng CAST() chức năng để chuyển đổi các trường số nguyên thành văn bản, và nó sẽ làm việc:

SELECT request_id, md5(CAST(request_id AS TEXT)) 
FROM Request 
ORDER BY request_id 

--1;"c4ca4238a0b923820dcc509a6f75849b" 
--2;"c81e728d9d4c2f636f067f89cc14862c" 
--etc 
3

Nói chung nó không có ý nghĩa nhiều để có những md5 của một số nguyên. Dường như bạn cố che khuất một chuỗi để nó xuất hiện một cách ngẫu nhiên theo thứ tự. Nếu có, có cách tốt hơn nhiều:

Sử dụng pseudo_encrypt function listed on the PostgreSQL wiki. Đó là cách saner hơn cố gắng để lấy md5 của một số nguyên sau đó (có lẽ) cắt nó.

Ở trên không không cung cấp tính ngẫu nhiên mã hóa mạnh mẽ, nhưng cũng không phải cách tiếp cận của bạn. Nếu bạn cần ID yêu cầu thực sự không thể đoán trước vì lý do bảo mật hơn là không rõ ràng, bạn nên sử dụng trình tạo số ngẫu nhiên mã hóa mạnh và được chuẩn bị để đối phó với các bản sao bằng cửa sổ thời gian, v.v.

+0

Tôi chỉ đang cố gắng tạo ra một giá trị không lặp lại, không lặp lại, có thể được sử dụng để tra cứu một bản ghi. Vì vậy, ý tưởng sáng sủa của tôi (?) Là thực hiện một số loại mã hóa trên PL của kẻ lừa đảo. Việc bảo mật bằng cách ẩn danh được thực hiện cần thiết vì người dùng thông thường (người yêu cầu vé) sẽ không có thông tin đăng nhập. Dù sao, tôi đã sử dụng 'REPLACE (request_id :: text, '1234567890', 'abcdefghij')' để làm điều này "mã hóa". –

+0

PS - "Awooga! Awooga!" Của bạn vẫn làm tôi khó chịu. –

+1

@ JeromyFrench Tôi có thể nói gì, tôi yêu Holly và chỉ thích đùa thôi, chỉ những người già chúng tôi mới nhận được ;-). Giống như một giảng viên, tôi đã có mặt ở trường đại học mà đã tạo ra những tài liệu khỉ cực kỳ ngộ nghĩnh trong các cuộc nói chuyện của cô ấy; bốn hay năm người trong nhà hát sẽ cười phá lên và mọi người khác sẽ nhìn chúng tôi như thể chúng tôi đã phát điên. –

0

I'm just trying to generate a non-obvious, non-repeating, value which can be used to look-up a record.

Những gì bạn cần là một băm sinh học. Tôi sử dụng chức năng CPU CRC trong chức năng C tùy chỉnh. Đối với các CPU không có hàm, người ta có thể sử dụng bảng tra cứu.

Cách tiếp cận này được đảm bảo cung cấp cho bạn một số "tìm kiếm ngẫu nhiên" duy nhất cho mỗi đầu vào 32 bit duy nhất.

Nếu bạn biết cách tạo các hàm C (không tầm thường), nó sẽ là một nhiệm vụ đơn giản để tìm cách sử dụng CRC.

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