2017-11-23 14 views
1

인보이스에 고유 ID를 만들어야합니다. 각 인보이스 ID는 & 달의 인보이스 및 1부터 시작하는 증분 숫자로 구성된 year-month-number 양식입니다 (간격은 허용되지 않음). 우리 월 2017 년 4 송장이있는 경우 PHP & MySQL : 고유 한 '년 - 월 - 숫자'키를 만드는 방법은 무엇입니까?

그래서 예를 들어, 나는 다음과 같은 4 송장 아이디의있을 것입니다 :
2017-1-1 
2017-1-2 
2017-1-3 
2017-1-4 

지금 나는이 고유 ID의를 생성하는 응용 프로그램을 만들려고합니다. 특히 2 명의 사람이 동일한 시간에 인보이스 번호를 요청할 때도 다른 ID를 가져야합니다.

나는 이노를 사용하고 난 다음 표

송장는 year-month 쌍에 대해 생성되지 않은 경우 책

year | month | number | 
------------------------ 
2017 | 7  | 2  | 
2017 | 6  | 5  | 
2017 | 5  | 6  | 

는 다음 엔트리가 데이터베이스에 없습니다 있습니다. 기본 키는 year-month 쌍이며 numberauto increment index입니다. 그 auto increment columnLAST_INSERT_ID(number+1) 다른 사용자에 의해 어쩌면 또한 (마지막으로 삽입 된 number을 증가하기 때문에 열 번호를 반환 $db->insert_id; :

$stmt = $db->prepare('INSERT INTO book(year,month,number) 
         VALUES (?,?,1) 
         ON DUPLICATE KEY UPDATE number= LAST_INSERT_ID(number+1)'); 
$stmt->bind_param('ii', $year, $month); 
$stmt->execute(); 
echo 'Next invoice id: ' . $year . '-' . $month . - . $db->insert_id; 

설명 :

내가이 같은 다음 송장 ID를 계산하는 것입니다 가정 ? 나는 그것에 대해 확실하지 않고 문서에서 이것을 찾는 데 문제가있다 http://dev.mysql.com/doc/refman/5.7/en/information-functions.html#function_last-insert-id)

사람들이이 코드를 동시에 실행하면이 코드가 실제로 작동할까요 아니면 여러 개의 동일한 ID를 만들 수 있습니까?

편집 현재 월/년의 수를 가정하는 이유는 두 쿼리가 동시에 6 숫자 5를 업그레이드 할 수 있도록 2 명, 같은 시간에 청구서를 계산한다는 것이 불가능하다 5. 입니다 ? 이 경우 청구서 ID '2017-11-6'을 모두 받게됩니까?

+0

는 당신이를 필요는 없습니다 AI 컬럼? 그렇지 않으면 자동으로 모든 레코드를 고유하게 만듭니다. –

+0

@ Fred-ii-'number' 필드는'AI' 칼럼이지만, 업데이트 할 때 증가시킵니다. – Adam

+0

AI를 증가 시켜서는 안되며, AI 자체가 증가합니다. 나는 당신이 여기서 무엇을하고 싶은지를 완전히 파악하지 못하고 있다고 느낍니다. mysqli_error ($ db)를 질의에 추가하고 그 결과를 볼 수 있습니까? –

답변

1

이와 같은 질문은 두 개의 터미널 창을 열고 mysql 클라이언트를 사용하여 시도 할 수 있습니다.

mysql1> select * from book; 
+------+-------+--------+ 
| year | month | number | 
+------+-------+--------+ 
| 2017 |  5 |  5 | 
+------+-------+--------+ 
는 두 개의 동시 세션에서 트랜잭션을 시작

:

mysql1> begin; 

mysql2> begin; 

세션 1은 IODKU 수행하고 수를 증가 (그러나 begin 암시 자동 커밋 모드에서 우리를 필요하기 때문에, 아직 커밋하지 않습니다) :

mysql11> insert into book values (2017, 5, 0) 
    on duplicate key update number = last_insert_id(number+1); 

mysql1> select * from book; 
+------+-------+--------+ 
| year | month | number | 
+------+-------+--------+ 
| 2017 |  5 |  6 | 
+------+-------+--------+ 

세션 2는 반복 가능한 읽기 트랜잭션 격리로 인해 원래의 숫자 값을 계속 볼 수 있습니다. 하지만 일단 자신이 증가 시키려고하면 세션 1에 여전히 행이 잠겨 있기 때문에 기다립니다.세션이 개 완료 지금

mysql1> commit; 

IODKU을, 우리는이 숫자를 두 번째로 증가 볼 수 있습니다 :

mysql2> select * from book; 
+------+-------+--------+ 
| year | month | number | 
+------+-------+--------+ 
| 2017 |  5 |  5 | 
+------+-------+--------+ 
mysql12> insert into book values (2017, 5, 0) 
    on duplicate key update number = last_insert_id(number+1); 
-- waits for lock 

세션 1 커밋

mysql2> select * from book; 
+------+-------+--------+ 
| year | month | number | 
+------+-------+--------+ 
| 2017 |  5 |  7 | 
+------+-------+--------+ 
+2

을 참조하십시오. 이렇게하면 첫번째 삽입물에'LAST_INSERT_ID'를 설정하지 않게됩니다. 그것을 수정하려면'도서 값 (2017, 5, last_insert_id (1)) ... '에 삽입해야합니다. –

+0

감사합니다. 또한 2016 년 7 월의 마지막 답변에 큰 도움이됩니다. P. 나는 $ stmt = $ db-> prepare ... $ stmt-> execute'가 mysql1 begin과 같은 이유를보기 위해 더 깊이 파고 들어야한다고 생각한다. ... mysql1> 커밋; 하지만 확실한 것은 -이게 무지한 권리 없이는 효과가 없을 것입니다. - 사실 지금은 그것을 테스트 할 수 있습니다 : D. – Adam

+0

@PaulSpiegel 멋진 수정, 감사합니다! – Adam