2011-08-30 68 views
8

Tôi đang sử dụng PHP/MySQL, để tạo mã truy cập cho từng mục nhập trong khi mở màn hình nhập.tạo mã truy cập để nhập cơ sở dữ liệu

Đây là mã tôi đang sử dụng

$qresult = $db->query("SELECT count(*) FROM ap_aurora_projects"); 
$row = $qresult->fetch_row(); 
$slno = $row[0] + 1; 

$today = date("ymd"); 

$code = $today . "-" . $slno; 

Mã này được tạo ra một cách chính xác và hiển thị cho người dùng trước khi ông tạo ra kỷ lục. Vấn đề là khi nhiều người dùng mở cùng một lúc mã được sao chép trong màn hình của họ.

Phương pháp để tránh trùng lặp là gì.

Tôi đã cố gắng tạo một bảng riêng để lưu số mới nhất và tăng lên cho mỗi yêu cầu, nhưng vấn đề là, nếu người dùng hủy mục nhập, số đó bị thiếu.

EDIT

Mã này được hoạt động bình thường khi một người sử dụng tạo mã và chèn các bản ghi. Nhưng vấn đề là nếu nhiều người dùng mở cùng một lúc nó tạo ra cùng một số cho họ trong màn hình của họ. Nếu tất cả chúng cố gắng lưu bản ghi, nó sẽ bị trùng lặp. Xin lưu ý rằng, tôi tạo số này và hiển thị trong màn hình nhập ban đầu không phải trong khi lưu bản ghi.

+0

Mã trùng lặp chính xác như thế nào? Tôi chỉ có thể thấy truy vấn SELECT an toàn và tất cả người dùng sẽ thấy cùng một đầu ra trừ khi DB thay đổi trong một số phần khác của mã. Bạn nên cung cấp thêm mã của mình. –

+0

cách các bản ghi ap_aurora_projects được chèn vào? mọi yêu cầu? –

+0

Mã nào có yêu cầu? Tuy nhiên, bạn không thể sử dụng COUNT() của các hàng nếu bạn cần hiển thị mã trước INSERT(). –

Trả lời

7

Tôi cho rằng mã bạn hiển thị trong câu hỏi được đơn giản hóa và bạn không thể sử dụng cột AUTO_INCREMENT như được đề xuất bởi câu trả lời khác.

Bạn cần khóa bàn để đọc cho đến khi được cập nhật.Làm các truy vấn MySQL theo thứ tự sau:

LOCK TABLES ap_aurora_projects READ; 
SELECT count(*) FROM ap_aurora_projects WHERE ...; 
//Update here ... 
UNLOCK TABLES; 

Thông tin thêm về khóa toàn bộ bảng có thể được tìm thấy ở đây: http://dev.mysql.com/doc/refman/5.6/en/lock-tables.html

Nếu bạn đang sử dụng công cụ lưu trữ InnoDB, bạn có thể đọc thêm về tiên tiến (hàng) khóa và giao dịch ở đây: http://dev.mysql.com/doc/refman/5.6/en/innodb-transaction-model.html

+0

Nó có thể không giúp đỡ trong trường hợp của tôi, vì tôi cần phải cho phép nhiều người dùng để tạo ra số tại một thời điểm. – AjayR

+1

Nó sẽ hoạt động vì câu lệnh 'LOCK TABLE' sẽ đợi cho đến khi tập lệnh khác kết thúc và nhả khóa. (nếu bảng đã bị khóa) –

4

Tạo số nhận dạng tự động làm mới của bạn rất khó và dễ bị lỗi như bạn đã phát hiện. Bạn nên suy nghĩ về việc sử dụng MySQL AUTO_INCREMENT feature và hàm LAST_INSERT_ID() tương ứng sẽ trả về id của bản ghi được chèn gần đây nhất trong phiên đó.

trích chính từ liên kết đó:

Những chức năng kết nối cụ thể, vì vậy giá trị trả về của họ được không bị ảnh hưởng bởi một kết nối khác cũng được thực hiện chèn.

Tuy nhiên, bạn sẽ phải thay đổi cách tiếp cận của mình. Thay vì hiển thị một ID trong màn hình trước khi bản ghi được tạo, bạn sẽ cần đợi đến khi chèn bản ghi. HOẶC nếu bạn THỰC HIỆN cần hiển thị ID này, sau đó chèn một bản ghi trống để tạo và trả lại ID và sau đó chỉnh sửa bản ghi đó từ dữ liệu do người dùng nhập thay vì thực hiện chèn.

Một ý tưởng đáng lo ngại là bạn cần hiển thị khóa chính bên trong cho người dùng của hệ thống. Chìa khóa không phải là tự nhiên (các định danh do chính phủ cấp) và nó được tạo ra bởi hệ thống. Điều này có mùi một chút thiết kế xấu. Thông thường các giá trị khóa chính không bao giờ được hiển thị cho người dùng và một số số nhận dạng thay thế khác được sử dụng.

+0

Tôi hoàn toàn đồng ý với bạn. Tuy nhiên, đây là số là một số loại số tham chiếu (không phải là số nhận dạng hàng) cho những người dùng sẽ ghi lại số đó để liên lạc thêm. – AjayR

+0

Phải. Điều đó có ý nghĩa nhưng tôi không thấy tại sao số tham chiếu phải tồn tại trước khi đối tượng kinh doanh thực sự tồn tại trong cơ sở dữ liệu ... hoặc tại sao nó dường như phải là một tập hợp các số nguyên tăng dần đơn điệu. Có một số cách khác để tạo ID duy nhất. –

6

đây là những gì bạn cần làm:

Đầu tiên, tạo một bảng:

create table uniqueId (id bigint(20) unsigned not null auto_increment primary key); 

Thứ hai, sử dụng mã này (tôi không biết đó là MySQL mã bạn sử dụng, vì vậy tôi sẽ sử dụng một trong những phổ biến):

$link = mysql_connect('localhost', 'user', 'password'); 
if (!$link) { 
    die('Could not connect: ' . mysql_error()); 
} 
mysql_select_db('mydb'); 
mysql_query("INSERT IGNORE INTO uniqueId VALUES (NULL);"); 
printf("Last inserted record has id %f\n", date("ymd") . "-" . mysql_insert_id()); 

Bằng cách chèn và không chọn, bạn chắc chắn sẽ không có bản sao.

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