field แบบนี้ ควรจะแยก ออกเป็นอีกตารางหรือไม่คะ ตรง ฟิลด์ BookID นะคะมันจะเป็น "ประเภท ปี
เวลาประกอบ เปน bookid ก็จะกลายเป็น OTHR201004-001,OTHR201004-002,HOME201004-001,HOME201004-002
Date :
2010-06-29 13:40:04
By :
แพร
เข้าใจค่ะ ปัญหาทั้งสองข้อเกิดจากการออกแบบ APP LAYER ไม่ดี ทั้ง UI และ BL ค่ะ
เข้าใจว่าของเดิมต้องกรอก manual อันนี้ไม่วิเคราะห์ละว่าทำอย่างนั้นทำไม
ในเมือเราเขียนโปรแกรมก้อเพื่ออำนวยความสะดวกไม่ใช่เพิ่มภาระให้กับ user
ในความเห็นนะคะ ควรเพิ่มตาราง BOOK_TYPE ขึ้นมา
เพื่อใช้อ้างอิงประเภทของการ BOOK จริงอยู่ในปัจจุบันมีแค่
HOME กับ OTHER แต่ถ้าเราสามารถเพิ่มลดประเภทได้ในอนาคต LOGIC
ของโปรแกรมก็ไม่เสียหายแต่อย่างใดค่ะ
นี่เป็นโครงสร้างของ TABLE BOOK_TYPE ค่ะ
Code (PHP)
=====================================================
NAME TYPE COMMENT
=====================================================
ID INT (AUTO) PRIMARY KEY
ITEM VARCHAR(100) BOOKED TYPE IDENTIFICATION NAME
ABBV VARCHAR(20) ABBREVIATE NAME FOR ANY PURPOSE
SEQUENCE INT PRESEREVED FOR MANNUAL ORDER
COMMENT TEXT KEEP DETAIL INFORMATION
นี่เป็น SCRIPT ที่ใช้สร้างนะคะ
Code (PHP)
DROP TABLE IF EXISTS `book_type`;
CREATE TABLE `book_type` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`item` varchar(100) DEFAULT NULL,
`abbv` varchar(20) DEFAULT NULL,
`sequence` int(10) unsigned DEFAULT NULL,
`comment` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=tis620;
แล้วก็ insert ค่า ลงไป
Code (PHP)
insert book_type (item ,abbv ,sequence ) values ('HOME' ,'HOME' ,1);
insert book_type (item ,abbv ,sequence ) values ('OTHER' ,'OTHR' ,999);
ส่วนตอนใช้งาน นั้นไม่ต้องแยก BOOKID ออกค่ะเรามาตัดต่อ STRING เอา
ด้วยเหตุผลเหมือนเดิมคือ เรามีกระบวนการอีกหลายอย่างนอกจากจะมาป้อนข้อมุลค่ะ
สังเกตุอย่างนึง นี่ใช้ WORD ออกแบบมาป่าวคะ รูปประกอบนีค่ะ
ก่อนจะไปขั้นต่อไป ขอถาม background นิดนึงค่ะ
เรียนหรือทำงานคะ เขียนภาษาไหนเป็นบ้าง
แล้วงานนี่คิดจะทำใหม่เอง หรือไปปรับปรุงงานคนอื่นคะ
พูดตรงๆนะคะ
คือรุสึกว่าคุณคิดแปลกๆ ไม่ใช่แบบนอกกรอบอะค่ะ
แบบทำให้จบเฉพาะงานไปไม่ได้คำนึงข้างหน้าข้างหลังเท่าไหร่
แล้วจะได้ประมาณเนื้อหาได้ถูกค่ะ
Date :
2010-06-29 14:21:51
By :
blurEyes
ขอบคุณ นะค๊าคุณ Stupid gal
ITEM : ประเภทของ book คือ OTHR / HOME
ABBV : คืออะไรนะคะ
SEQUENCE : นี่คือลำดับของประเภทนั้นๆ ใช้ป่าวคะ
ข้อมูล bookid ที่เป็น OTHR1006-001
ไม่ต้องแยกออกมาเป็นตารางก็ได้ใช่ไหมค่ะ แล้วค่อยใช้ sql ในการ ตัดสตริง แล้วค้นหาเอา ??
แล้วเวลา insert ถ้าเราจะมีให้เค้าเลือก ปี เดือน แล้วก็ ลำดับ อาจจะ ใช้วิธีการค้นหา ลำดับที่มากที่สุดของประเภท (4ตัวอักษรด้านหน้า) เวลา ล่าสุดลำดับเท่าไหร่
เค้าจะได้คีย์ต่อได้
อ่า มันแย่ป่าวคะวิธีนี้
Date :
2010-06-29 15:09:10
By :
แพร
Quote: แล้วเวลา insert ถ้าเราจะมีให้เค้าเลือก ปี เดือน แล้วก็ ลำดับ อาจจะ ใช้วิธีการค้นหา ลำดับที่มากที่สุดของประเภท (4ตัวอักษรด้านหน้า) เวลา ล่าสุดลำดับเท่าไหร่
ถ้าคุณมีการค้นหาการ BOOK เป็นวันก้อแยก FIELD ไปอีก
จากกระทู้คราวก่อน STRUCTURE น่าจะเป็นแบบนี้ค่ะ
Code (PHP)
=====================================================
NAME TYPE COMMENT
=====================================================
ID INT (AUTO) PRIMARY KEY
INV_NO VARCHAR(100) INVOICE NUMBER
SHIP_DATE DATE ITEM SHIP DATE
DESTINATION_COUNTRY VARCHAR(100) DESTINATION COUNTRY
DOCCUMENT_ARRIVED_DATE DATE DOCCUMENT ARRIVED DATE
BOOK_ID VARCHAR(100) BOOKED NUMBER
BOOK_TYPE INT INDEX TO BOOK_TYPE TABLE
BOOK_DATE DATE BOOKED DATE
COMMENT TEXT ANY COMMENT
DROP TABLE IF EXISTS `registry`;
CREATE TABLE `registry` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`inv_no` varchar(100) DEFAULT NULL,
`ship_date` datetime DEFAULT NULL,
`destination_country` varchar(100) DEFAULT NULL,
`document_arrived_date` datetime DEFAULT NULL,
`book_id` varchar(100) DEFAULT NULL,
`book_type_id` int(10) unsigned DEFAULT NULL,
`book_date` datetime DEFAULT NULL,
`comment` text,
PRIMARY KEY (`id`),
KEY `registry_FK1` (`book_type_id`),
CONSTRAINT `registry_FK1` FOREIGN KEY (`book_type_id`) REFERENCES `book_type` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=tis620;
ซึ่งจะมี relation กับ ตาราง book_type ก่อนหน้านี้ค่ะ
เพิ่ม field ที่เกี่ยวข้องลงไปเพื่อช่วยให้การ SEARCH ด้วยวันเวลาและประเภทของการ BOOK
ซึ่งจะทำให้ SEARCH ให้ รวดเร็วมากค่ะ
ส่วน สูตรในการ ทำ Book_id ใช้ STORE PROCEDURE ใน MySQL นะคะ
Code (PHP)
DELIMITER $$
DROP FUNCTION IF EXISTS `GET_BOOK_ID` $$
CREATE DEFINER=`root`@`localhost` FUNCTION `GET_BOOK_ID`(_BOOK_TYPE_ID INT, _BOOK_DATE DATETIME) RETURNS varchar(100) CHARSET tis620
BEGIN
DECLARE _DATE_PART VARCHAR(100) DEFAULT '' ;
DECLARE _COUNTER INT DEFAULT 0 ;
DECLARE _TEMP_STR VARCHAR(100) DEFAULT '' ;
DECLARE _PREFIX_STR VARCHAR(100) DEFAULT '' ;
DECLARE _SEPARATOR VARCHAR(10) DEFAULT '-' ;
DECLARE _DUMM_ID_STR VARCHAR(100) DEFAULT 'X-0' ;
DECLARE _STR_RET VARCHAR(100) DEFAULT '';
SET _DATE_PART = DATE_FORMAT(_BOOK_DATE ,'%Y%m') ;
SELECT `ABBV` INTO _TEMP_STR
FROM `BOOK_TYPE` WHERE `ID` = _BOOK_TYPE_ID ;
/* COMPOSE RUNNO'S PREFIX PART */
SET _PREFIX_STR = CONCAT(_TEMP_STR ,_DATE_PART, _SEPARATOR) ;
SET _TEMP_STR = CONCAT(_PREFIX_STR, '%') ;
SELECT IFNULL(MAX(BOOK_ID), _DUMM_ID_STR) INTO _TEMP_STR
FROM `REGISTRY` WHERE BOOK_ID LIKE _TEMP_STR ;
/* GET COUNTER PART */
SET _TEMP_STR = SUBSTRING(_TEMP_STR ,INSTR(_TEMP_STR ,_SEPARATOR)+1 ) ;
/* EXTRACT AND INCREASING COUNTER */
SET _COUNTER = CONVERT(_TEMP_STR ,SIGNED) +1;
/* DECORATE COUNTER */
SET _TEMP_STR = CONVERT(_COUNTER ,CHAR) ;
/* ADDING 0 */
SET _TEMP_STR = LPAD(_TEMP_STR, 7, '0');
/* FINALLY COMPOSE */
SET _STR_RET = CONCAT(_PREFIX_STR, _TEMP_STR) ;
RETURN _STR_RET ;
END $$
DELIMITER ;
ลอง TEST ดู ผลก็ OK ค่ะ
Code (PHP)
insert into `registry` ( inv_no, ship_date, destination_country
, document_arrived_date
, book_id, book_type_id, book_date )
values
( '4084424209', CURRENT_DATE() ,'USA'
, ADDDATE(CURRENT_DATE() ,INTERVAL -2 DAY)
, GET_BOOK_ID(1, ADDDATE(CURRENT_DATE() ,INTERVAL -5 DAY))
, 1, ADDDATE(CURRENT_DATE() ,INTERVAL -5 DAY)) ,
( '4084424210', CURRENT_DATE() ,'CANADA'
, ADDDATE(CURRENT_DATE() ,INTERVAL -2 DAY)
, GET_BOOK_ID(1, ADDDATE(CURRENT_DATE() ,INTERVAL -5 DAY))
, 1, ADDDATE(CURRENT_DATE() ,INTERVAL -5 DAY)) ,
( '4084424211', CURRENT_DATE() ,'UK'
, ADDDATE(CURRENT_DATE() ,INTERVAL -2 DAY)
, GET_BOOK_ID(2, ADDDATE(CURRENT_DATE() ,INTERVAL -5 DAY))
, 2, ADDDATE(CURRENT_DATE() ,INTERVAL -5 DAY)) ,
( '4084424212', CURRENT_DATE() ,'GERMAN'
, ADDDATE(CURRENT_DATE() ,INTERVAL -2 DAY)
, GET_BOOK_ID(2, ADDDATE(CURRENT_DATE() ,INTERVAL -5 DAY))
, 2, ADDDATE(CURRENT_DATE() ,INTERVAL -5 DAY))
;
มีข้อแนะนำอีกเรื่องคือ field : destination_country
น่าจะแยกออกมาแบบเดียวกับ book_type เพื่อป้องกันการ key พลาด
เช่น USA ,usa หรือ U.S.A จะถือว่าเป็นคนละประเทศค่ะ
Date :
2010-06-30 07:21:11
By :
blurEyes
*0* สุดๆๆๆๆๆๆๆๆๆๆๆๆๆๆๆๆๆๆๆๆๆๆๆๆๆ ขอบคุณ มากๆๆๆๆ เลยค๊า
เด่วต้องเอาไปศึกษาเพิ่มเติมมมเยอะๆ
Date :
2010-06-30 11:06:10
By :
แพร
อ้อลืมบอกไป
ABBV : ABBREVIATE คำย่อค่ะ ไว้ใช้อ้างตอนสร้่าง run no
Date :
2010-06-30 11:46:10
By :
blurEyes
Code (PHP)
/* GET COUNTER PART */
SET _TEMP_STR = SUBSTRING(_TEMP_STR ,INSTR(_TEMP_STR ,_SEPARATOR)+1 ) ;
/* EXTRACT AND INCREASING COUNTER */
SET _COUNTER = CONVERT(_TEMP_STR ,SIGNED) +1;
ตรง SET _TEMP_STR เป็นการตัดสตริง เช่น HOME1006-001 ก็จะตัดตัว HOME1006- ออก _TEMP_STR จะเป็น 001 ใช่ปะคะ
แล้ว พอมาที่ _COUNTER คือเปลี่ยนชนิดข้อมูลจาก 001 เป็น ชนิดเลขหลักบวกเท่านั้น SIGNED ถูกมั้ยคะ แต่ ค่าที่ได้จาก CONVERT(_TEMP_STR ,SIGNED) เป็นค่าอะไรหรอ มันถึงจะบวก 1 ได้
อ่าพอดี ยังไม่เคยใช้คำสั่งนี้อ่ะคะ
ขอบคุณมากกกกกๆๆๆๆค๊า
Date :
2010-06-30 13:31:20
By :
แพร
อ๋อ ก็จะได้ เป็น counter = 1+1 = 2 ใช่ป่าวคะ
Date :
2010-06-30 13:33:15
By :
แพร
SET _TEMP_STR ใช่ค่ะเป็นการตัดท่อน counter ออกมา
แต่ค่าที่ได้ยังเป็น string อยู่
ส่วน
SET _COUNTER = CONVERT(_TEMP_STR ,SIGNED) +1
CONVERT(_TEMP_STR ,SIGNED) จะเป็นการแปลงกลับไปเป็น INTEGER
และเนื่องจากเป็น COUNTER ค่าใหม่ต้องเพิ่มขึ้น จึง +1 ค่ะ
Date :
2010-06-30 13:35:51
By :
blurEyes
จากตารางที่แยก book_id
ตารางที่ชื่อว่า book_type อะคะ
ตอนที่แอดข้อมูล
Code (PHP)
insert book_type (item ,abbv ,sequence ) values ('HOME' ,'HOME' ,1);
insert book_type (item ,abbv ,sequence ) values ('OTHER' ,'OTHR' ,999);
sequence เป็น 1,999
นี้คือะไรหรออคะ
ในตารางนี้ ก็จะมีแค่ 2 record ไว้ใช้อ้างอิงในตารางอื่นๆ ใช่มั้ยคะ
Date :
2010-06-30 13:46:16
By :
แพร
ใช่ค่ะ ที่กำหนดให้เป็น ลำดับที่ 999 เพราะธรรมชาติของข้อมูล
อะไรก้อตามที่เป็น OTHER มักจะอยู่ลำดับ หลังสุด
ในกรณีที่วันนึงเราเพิ่มข้อมูลและอยากให้ลำดับของข้อมูลใหม่
มาก่อน OTHER ก้อกำหนดลำดับ ให้น้อยกว่า 999 ค่ะ
เช่น
insert book_type (item ,abbv ,sequence ) values ('URGENT' ,'URGN' ,200);
Date :
2010-06-30 13:51:25
By :
blurEyes
Code (PHP)
insert book_type (item ,abbv ,sequence ) values ('HOME' ,'HOME' ,1);
insert book_type (item ,abbv ,sequence ) values ('URGENT' ,'URGN' ,2);
insert book_type (item ,abbv ,sequence ) values ('OTHER' ,'OTHR' ,3);
อย่างนี้ได้ป่าวคะ ทำเพื่อ จุดประสงค์ ยังไงบ้างหรอคะ (งงๆ นิ๊ดๆ อยากเข้าใจอะคะ)
Date :
2010-06-30 13:55:01
By :
แพร
ก้อได้ค่ะ ^^
ถ้าอย่างนั้นจะไม่ค่อยยืดหยุ่นเท่าไหร่ เท่านั้นเองค่ะ
เช่นสมมุติมีอีกค่านึง มาใหม่แล้วมีลำดับก่อน URGENT
มันจะไม่มีที่ลงเท่านั้นเองค่ะ
คิดเผื่อเหลือเอาไว้ในอนาคตน่ะค่ะ
ว่ากันตามหลักแล้ว น่าจะเขียนนแบบนี้มากกว่าค่ะ
Code (PHP)
insert book_type (item ,abbv ,sequence ) values ('HOME' ,'HOME' ,100);
insert book_type (item ,abbv ,sequence ) values ('OTHER' ,'OTHR' ,999);
Date :
2010-06-30 14:06:47
By :
blurEyes
เอ แล้วจุดประสงค์ sequence มันจะมีผลยังไงบ้างหรอคะ
Date :
2010-06-30 14:11:43
By :
แพร
หรือว่า เอาไปใช้เรียงข้อมูล เวลาแสดง อะคะ
Date :
2010-06-30 14:17:40
By :
แพร
ถูกค่ะ เพราะปกติ id จะเรียงให้ตามลำดับก่อนหลังของการ key ข้อมุลให้
และหากเราต้องการ ให้เรียงตาม ชื่อ ก็ SORT เอาด้วย ORDER BY ITEM
แต่ในกรณีที่ข้อมูลเรียงแบบตามใจฉัน 'ZEBRA' ,'LEOPARD' ,'BAT' ,'RABBIT'
เผื่อเอาไว้ให้กรณีอย่างนี้น่ะค่ะ
ก็อย่างที่บอกเผื่อเอาไว้บางที่เราไม่ค่อยได้ใช้หรอกค่ะ แต่ถ้าได้ใช้เมื่อไหร่
ก็แทบจะไม่ต้องแก้ code เลย
concept คือให้ยืดหยุ่นในระดับนึงอะค่ะ
Date :
2010-06-30 14:26:07
By :
blurEyes
อ๋ออออออออออออออเข้าใจเรย
ขอบคุณ มากกกกกกกกกกกกกกกกกกกกกก เลยนะคะ สุดๆ :DDD
Date :
2010-06-30 14:37:34
By :
แพร
ถ้า id มันเป็น HOME1006-001, HOME1006-002, OTHR1006-001,HOME1006-003,OTHR1006-002
*แล้วรหัสนี้ จะใช้ store procedure เป็นตัวรันรหัสให้ (จาก code ข้างบนอะ)
*เราให้ field id ตรงนี้เป็น pk ได้เรยป่าว
*เพราะมันไม่ซ้ำกัน
*แต่ต้องผ่านกระบวนการ store procedure ก่อน
Date :
2010-07-04 12:04:15
By :
แพร
Load balance : Server 05