-
01-05-2011, 05:42 PM #1Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Hướng dẫn tạo mã tự động kế tiếp trên C# và SQL server (trigger)
Hàm này dùng để tạo tự động mã kế tiếp giống như AutoCrement, nhưng AutoCrement chỉ tạo được đối với kiểu dữ liệu integer. Vậy nếu bạn muốn tạo mã kế tiếp với mã có chứa ký tự "HS0009" thì sao?
VD: Mã học sinh cuối cùng trong bảng CSDL là HS0009, thì khi gọi hàm này nó sẽ tìm ra mã tiếp theo là HS0010, và nếu mã này là HS9999 thì mã kế tiếp sẽ là HS10000
Để lấy mã số cuối cùng trong CSDL thì ta dùng query sắp xếp giảm dần là lấy được thoi
VD: SELECT TOP 1 MAHS FROM HOCSINH ORDER BY MAHS DESC
Với query trên sẽ trả về cho ta MAHS cuối cùng trong CSDL với điều kiện mã số đó phải fix width (cố định số ký tự có trong mã). Còn nếu bạn sử dụng mã không cố định số ký tự thì không dùng query trên được đâu. VD: Tôi có danh sách mã HS1,HS2,HS3,...,HS9,HS10,HS11 thì theo bạn mã tiếp theo nếu dùng query trên là gì? Nó sẽ trả về HS9 đấy! Vì mã sau khi sort thì HS9 là mã cuối cùng được trả về! Trong trường hợp này bạn phải viết 1 hàm lấy tất cả mã số, và duyệt tất cả mã số đó tách bỏ phần tiền tố "HS" đi cho vào mảng và sắp xếp giảm dần, ta lấy phần tử mảng đầu tiên đó là mã số ID cuối cùng! Với cách này thì nó sẽ tìm mã kế tiếp lâu hơn, bạn có thể viết StoreProcedure để chạy dưới CSDL thì nhanh hơn!
Đây là hàm lấy mã cuối cùng theo query order by, với tham số truyền vào:
+ nameTable: Tên table vd ở trên là HOCSINH
+ nameSelectColumn: Tên filed muốn lấy vd MAHS
+ Trong hàm có ExecuteScalar(sql) là hàm trả về giá trị first row, first field tìm được
Mã:public string GetLastID(string nameTable, string nameSelectColumn){ string sql = "SELECT TOP 1 " +nameSelectColumn +" FROM " + nameTable + " ORDER BY " + nameSelectColumn + " DESC"; return (string)ExecuteScalar(sql);}
+ lastID: chuỗi mã cuối cùng vừa tìm được từ hàm GetTopDataCell()
+ prefixID: Tiền tố mã. Với vd trên là "HS"
Mã:public string NextID(string lastID, string prefixID) { if(lastID = "") { return prefixID+"0001"; // fixwidth default } int nextID = int.Parse(lastID.Remove(0, prefixID.Length)) + 1; int lengthNumerID = lastID.Length - prefixID.Length; string zeroNumber = ""; for (int i = 1; i <= lengthNumerID; i++) { if (nextID < Math.Pow(10, i)) { for (int j = 1; j <= lengthNumerID - i; i++) { zeroNumber += "0"; } return prefixID + zeroNumber + nextID.ToString(); } } return prefixID + nextID; }
Mã:string lastID = GetLastID("HOCSINH","MAHS");string nextID = NextID(lastID,"HS");
Nhưng đối với mã dạng: KH8, KH9, KH10, KH11 khi sắp xếp DESC sẽ ra: KH9, KH8, KH11, KH10 vì nó sắp xếp ưu tiên các ký tự từ bên trái sang. Vậy để tìm mã cuối cùng của mã những dạng này thì làm sao?
- Lấy tất cả các mã trong CSDL
- Duyệt từng mã để tách tiền tố của mã, cho vào mảng và tìm phần tử lớn nhất
- Lấy phần tử đầu tiên của mảng và +1 để lấy mã tiếp theo
- Lấy mã này ghép với tiền tố mã là ta lấy được mã mới
Với cách này sẽ thực hiện chậm hơn nhiều so với mã fixwidth mà tôi nói ở trên
Giải thuật chưa được hay, bạn nào có giải thuật tối ưu thì góp vui nhé [IMG]images/smilies/online.gif[/IMG]
Mã:string sql = "SELECT MaKH FROM Customer";// Lấy DataTable từ câu truy vấn truyền vào (Apdapter Fill DataTable)DataTable tb = GetDataTable(sql);double[] arrCode = new double[tb.Rows.Count];int code;for(int i=0; i< tb.Rows.Count; i++){ code = int.Parse(b.Rows[i]["MaKH"].ToString().Remove(0,2)); arrCode[i] = code;}code = arrCode.Max() + 1;string nextID = "KH"+code;
View more random threads:
- Xây dựng một Single Assembly trong lập trình C#
- Kỹ thuật nén website MVC , Webform tăng tốc website
- Vlog 5: Hướng dẫn lập trình: Tạo captcha đơn giản với C#
- C# Tutorial - Từ cơ bản tới nâng cao
- Xác định google bot thăm website của bạn trong ASP.NET
- Chuyền values qua url "routes.MapRoute"(SEO google)
- xem dùm mình phương thức nhân hai ma trận với phương thức hai ma trận bằng nhau sao chương trình không thưc thi được vậy
- Video Demo tạo đa ngôn ngữ trong Asp.Net
- Hướng dẫn sử dụng thư viện CkFinder - Chèn ảnh trong CkEditor
- Xem nội dung file pdf trên web
-
01-05-2011, 05:44 PM #2Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Để đơn giản tìm mã có tiền tố kế tiếp trên C# (vd: HS009 => HS010) mình có 1 giải pháp như sau:
- Tạo function tìm mã kế tiếp từ mã cuối cùng như C#
- Dùng trigger for Insert tự động dùng function tìm mã ở trên để tạo ra mã kế tiếp
Function tìm mã kế tiếp, bạn chạy 1 lần để tạo function
Các tham số truyền vào:
+ @lastid : mã cuối cùng trong bảng muốn tìm nextid
+ @prefix : tiền tố mã (HS0009 => HS)
+ @size: số lượng ký tự trong mã (HS0009 => 6)
Mã:GOif exists (select * from sysobjects WHERE name = 'fn_NextID' AND type = 'fn') drop function fn_NextIDGO-- @lastid là mã cuối cùng (fixwidth)-- @prefix là tiền tố mã: vd HS0001 => HS-- @size là số lượng ký tự trong mã HS0001 => 6CREATE function fn_NextID (@lastid varchar(10),@prefix varchar(10),@size int) returns varchar(10)as BEGIN IF(@lastid = '') set @lastid = @prefix + REPLICATE (0,@size - LEN(@prefix)) declare @num_nextid int, @nextid varchar(10) set @lastid = LTRIM(RTRIM(@lastid)) -- number next id set @num_nextid = replace(@lastid,@prefix,'') + 1 -- bo di so luong ky tu tien to set @size = @size - len(@prefix) -- replicate số lượng số 0 REPLICATE(0,3) => 000 set @nextid = @prefix + REPLICATE (0,@size - LEN(@prefix)) set @nextid = @prefix + RIGHT(REPLICATE(0, @size) + CONVERT (VARCHAR(MAX), @num_nextid), @size) return @nextid END;
Mã:select dbo.fn_NextID ('','HS',6) -- HS0001 (mã đầu tiên)select dbo.fn_NextID ('HS0009','HS',6) -- HS0010
VD: tôi có bảng test (id,name) với id là mã
Mã:GOif exists (select * from sysobjects WHERE name = 'tr_NextID_Test' AND type = 'TR') drop trigger tr_NextID_TestGOcreate trigger tr_NextID_Test on testfor insertas begin DECLARE @lastid nvarchar(10) SET @lastid = (SELECT TOP 1 id from test order by id desc) UPDATE test set id = dbo.fn_NextID (@lastid,'HS',7) where id = '' end
Mã:insert test (id,name) values ('','abc')select * from test
Vệc tự động thêm trong SQL có vẻ đơn giản hơn nhỉ, nhưng bù lại các bạn phải xây dựng tất cả các trigger tương ứng với các bảng thêm. Chúc sức khỏe!
-
03-04-2012, 01:19 PM #3Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Bạn cho mình hỏi tí nha,
Mình đã làm thử theo cách của bạn và kết quả chạy okie, nhưng mình có thắc mắc vài chỗ nhờ bạn giải thích giúp:
1. Function fn_NextID được đưa vào bảng sysobjects nhưng khi mình vào System Table thì không có bảng này.
2. Mình có thể mở lại trigger tr_NextID_Test nhưng không thể tìm thấy trigger fn_NextID.
Vấn đề của mình ở đây là cần tìm vị trí của trigger fn_NextID.?
-
13-04-2012, 09:29 AM #4Junior Member
- Ngày tham gia
- Sep 2015
- Đang ở
- hà nội
- Bài viết
- 0
Những đoạn mã này rất hay, tuy nhiên bản thân nó còn có thể được nâng cấp lên một mức mới
Đối với những chuỗi này, cần phải define những con số sử dụng ngay từ đầu, như vậy những hàm này mới có thể được tái sử dụng nhiều lần
Vì một khi sử dụng những hàm này trong các dự án lớn thì chúng ta không bao giờ chỉ sử dụng một lần
nên truyền các tham số vào sẽ giúp cho việc sử dụng lại nhiều lần ở những table khác một cách dễ dàng hơn
Để nghiên cứu chút rồi có thể sẽ sửa chữa lại cho thích hợp hơn nữa.
Bài hướng dẫn này thật sự rất hay nhưng thường mình add trigger ngay bảng mình làm luôn chứ không đưa ra một bảng khác như trên
-
30-06-2012, 04:41 PM #5Administrator
- Ngày tham gia
- Feb 2014
- Bài viết
- 0
mình làm tương tự nhưng lại xuất hiện lỗi
mong đc giúp đỡ.
The name 'ExecuteScalar' does not exist in the current context
-
20-07-2012, 06:03 PM #6Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Các bạn ơi cho mình hỏi, giả sử trong bảng có 2 mã là H09 và H10, bây giờ mình thêm thì mã sẽ là H11, nhưng giả sử trong csdl của mình ko còn H10(do bị xóa) mà chỉ có H09 thì nó có tự động thêm mã H11 không? và nếu là mã tự động tăng thì mình phải viết câu lệnh sql ntn để lấy đc mã tiếp theo khi mình insert chứ ko phải là mã lớn nhất trong csdl nha. Mình cảm ơn các bạn!
-
14-08-2012, 05:17 PM #7Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Không cần phức tạp vậy đâu, cái auto này thực chất phụ thuộc vào số ID đó có bị xóa trong tương lai hay không, tức là có làm khóa chính hay không? Nếu làm khóa chính thì đâu xóa được, do đó bạn chỉ cần viết 1 cái store đơn giản là đếm tổng số mã, sau đó lấy tổng + 1 là ra 1 số mới, thay vào cái đuôi là trả ra mã mới!!! Còn nếu ko làm khóa chính bạn sẽ viết 1 cái store proc cho 1 vòng lặp kiểm tra xem nó bị đứt quãng chỗ nào thì thay thế vào, mình nghĩ mấy cái này khá đơn giản. Các bạn cứ thử xem, cái store chỉ cần vài dòng đơn gian nhưng vẫn chạy ổn định, mình vẫn thường làm như vậy trong các dự án phần mềm và chưa bao giờ chạy sai!!!!
-
05-10-2012, 05:59 PM #8Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Gửi bởi thien.mylove
lúc đó mình cần phải xét lại mã mình đã xóa để cấp lại khi thêm mới chứ???
-
07-12-2012, 09:43 AM #9Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Mình thì làm theo cách này :
Trước tiên tạo 1 bảng tên là ...gì thì tùy.Mình đặt là AutoID
Mã:create table AutoID ( Ma int identity primary key not null, Ten nvarchar(200), TienTo varchar(10), GiaTri int )
Sau đó tạo 1 cái hàm sinh mã tự động.
Mã:public string TaoMa(int maAutoID) { int giatri; try { string sql=String.Format("select * from AutoID where Ma='{0}'", maAutoID); SqlCommand cmd = new SqlCommand(sql,con); SqlDataReader read = cmd.ExecuteReader(); while (read.Read()) { string tiento = read.GetValue(2).ToString(); giatri = (int)read.GetValue(3); if (giatri==0) { ketqua = tiento + "00001"; } else { giatri = giatri + 1; if (giatri < 10) ketqua = String.Format("{0}0000{1}", tiento, giatri); else if (giatri >= 10 && giatri < 100) ketqua = String.Format("{0}000{1}", tiento, giatri); else if (giatri >= 100 && giatri < 1000) ketqua = String.Format("{0}00{1}", tiento, giatri); else if (giatri >= 1000 && giatri < 10000) ketqua = String.Format("{0}0{1}", tiento, giatri); else ketqua = tiento + giatri; } } read.Close(); } catch { XtraMessageBox.Show("Lỗi kết nối", "Chú ý", MessageBoxButtons.OK, MessageBoxIcon.Error); } return ketqua; }
Khi insert 1 bản ghi nào đó thì đồng thời ta lại update lại bảng AutoID cho trường value tăng lên 1.
-
17-12-2012, 09:28 AM #10Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Rất hay bạn ah. Phải thử gấp cho nóng
Bất chấp những lầm tưởng phổ quát, hồ hết những người có âm đạo đều khó lên đỉnh khi bị kích thích âm đạo. Tuy nhiên, điều đó không có tức thị nó không thể vui được! Việc xâm nhập vào âm đạo bằng...
Quý bà giải tỏa bằng việc kích...