Trang 1 trên tổng số 2 12 Cuối cùngCuối cùng
Từ 1 tới 10 trên tổng số 16 kết quả

Đề tài: Hướng dẫn tạo mã tự động kế tiếp trên C# và SQL server (trigger)

  1. #1
    Ngày gia nhập
    04 2010
    Bài viết
    73

    Mặc định 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

    Visual C# Code:
    1. public string GetLastID(string nameTable, string nameSelectColumn)
    2. {
    3.             string sql = "SELECT TOP 1 " +nameSelectColumn +" FROM " + nameTable + " ORDER BY " + nameSelectColumn + " DESC";
    4.             return (string)ExecuteScalar(sql);
    5. }

    Và đây là hàm tìm mã kế tiếp:
    + 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"

    Visual C# Code:
    1. public string NextID(string lastID, string prefixID)
    2.         {
    3.             if(lastID = "")
    4.            {
    5.                return prefixID+"0001";  // fixwidth default
    6.            }
    7.             int nextID = int.Parse(lastID.Remove(0, prefixID.Length)) + 1;
    8.             int lengthNumerID = lastID.Length - prefixID.Length;
    9.             string zeroNumber = "";
    10.             for (int i = 1; i <= lengthNumerID; i++)
    11.             {
    12.                 if (nextID < Math.Pow(10, i))
    13.                 {
    14.                     for (int j = 1; j <= lengthNumerID - i; i++)
    15.                     {
    16.                         zeroNumber += "0";
    17.                     }
    18.                     return prefixID + zeroNumber + nextID.ToString();
    19.                 }
    20.             }
    21.             return prefixID + nextID;
    22.  
    23.         }

    Gọi hàm:

    Visual C# Code:
    1. string lastID = GetLastID("HOCSINH","MAHS");
    2. string nextID = NextID(lastID,"HS");


    Đối với những dạng: KH008, KH009, KH010, KH011 như tôi nói ở trên khi sắp xếp DESC trong CSDL thì ra là: KH011, KH010, KH009, KH008 rất dễ để lấy mã cuối cùng để xử lý
    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é
    Visual C# Code:
    1. string sql = "SELECT MaKH FROM Customer";
    2. // Lấy DataTable từ câu truy vấn truyền vào (Apdapter Fill DataTable)
    3. DataTable tb = GetDataTable(sql);
    4. double[] arrCode = new double[tb.Rows.Count];
    5. int code;
    6. for(int i=0; i< tb.Rows.Count; i++)
    7. {
    8.     code = int.Parse(b.Rows[i]["MaKH"].ToString().Remove(0,2));
    9.     arrCode[i] = code;
    10. }
    11. code = arrCode.Max() + 1;
    12. string nextID = "KH"+code;


    Phần sau: Viết trigger thêm ID có tiền tố tự động (SQL server)

  2. #2
    Ngày gia nhập
    04 2010
    Bài viết
    73

    Mặc định Viết trigger thêm ID có tiền tố tự động (SQL server)

    Để đơ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)

    Visual C# Code:
    1. GO
    2. if exists (select * from sysobjects WHERE name = 'fn_NextID' AND type = 'fn')
    3.     drop function fn_NextID
    4. GO
    5. -- @lastid là mã cuối cùng (fixwidth)
    6. -- @prefix là tiền tố mã: vd HS0001 => HS
    7. -- @size là số lượng ký tự trong mã HS0001 => 6
    8. CREATE function fn_NextID (@lastid varchar(10),@prefix varchar(10),@size int)
    9.   returns varchar(10)
    10.     BEGIN
    11.         IF(@lastid = '')
    12.             set @lastid = @prefix + REPLICATE (0,@size - LEN(@prefix))
    13.         declare @num_nextid int, @nextid varchar(10)
    14.         set @lastid = LTRIM(RTRIM(@lastid))
    15.         -- number next id
    16.         set @num_nextid = replace(@lastid,@prefix,'') + 1
    17.         -- bo di so luong ky tu tien to
    18.         set @size = @size - len(@prefix)
    19.         -- replicate số lượng số 0 REPLICATE(0,3) => 000
    20.         set @nextid = @prefix + REPLICATE (0,@size - LEN(@prefix))
    21.         set @nextid = @prefix + RIGHT(REPLICATE(0, @size) + CONVERT (VARCHAR(MAX), @num_nextid), @size)
    22.         return @nextid
    23.     END;

    Sử dụng:

    Visual C# Code:
    1. select dbo.fn_NextID ('','HS',6)  -- HS0001 (mã đầu tiên)
    2. select dbo.fn_NextID ('HS0009','HS',6)  -- HS0010

    Tiếp theo ta sẽ viết trigger for insert để tự động thêm mã kế tiếp khi ta insert 1 bộ mới
    VD: tôi có bảng test (id,name) với id là mã

    Visual C# Code:
    1. GO
    2. if exists (select * from sysobjects WHERE name = 'tr_NextID_Test' AND type = 'TR')
    3.     drop trigger tr_NextID_Test
    4. GO
    5. create trigger tr_NextID_Test on test
    6. for insert
    7.     begin
    8.         DECLARE @lastid nvarchar(10)
    9.         SET @lastid  = (SELECT TOP 1 id from test order by id desc)
    10.         UPDATE test set id = dbo.fn_NextID (@lastid,'HS',7) where id = ''
    11.     end

    Test thử nhé:
    Visual C# Code:
    1. insert test (id,name) values ('','abc')
    2. select * from test

    Quét khối, mỗi lần ấn F5 sẽ cho ra mã kế tiếp như ý muốn. lưu ý tham số thứ nhất @lastid bỏ trống nhé!
    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!
    Đã được chỉnh sửa lần cuối bởi darknight1611 : 01-05-2011 lúc 11:03 PM.

  3. #3
    Ngày gia nhập
    03 2011
    Bài viết
    2

    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.?

  4. #4
    Ngày gia nhập
    04 2011
    Bài viết
    127

    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

  5. #5
    Ngày gia nhập
    11 2010
    Bài viết
    5

    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

  6. #6
    Ngày gia nhập
    04 2011
    Bài viết
    32

    Mặc định Hướng dẫn tạo mã tự động kế tiếp trên C# và SQL server (trigger)

    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!

  7. #7
    Ngày gia nhập
    03 2011
    Bài viết
    1

    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!!!!

  8. #8
    Ngày gia nhập
    08 2012
    Bài viết
    2

    Trích dẫn Nguyên bản được gửi bởi thien.mylove Xem bài viết
    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!!!!
    nếu mình cần xóa 1 đối tượng thì xóa luôn khóa chính chứ bạn???
    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ứ???

  9. #9
    Ngày gia nhập
    04 2011
    Bài viết
    7

    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
    Code:
    create table AutoID
    (
    	Ma int identity primary key not null,
    	Ten nvarchar(200),
    	TienTo varchar(10),
    	GiaTri int
    )
    Xem cụ thể hình bên dưới.
    Sau đó tạo 1 cái hàm sinh mã tự động.

    Code:
    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;
            }
    Cách này vừa có thể tạo mã tự tăng và cũng vừa có thể tạo mã do người dùng nhập vào rất linh hoạt.
    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.
    Attached Thumbnails Attached Thumbnails Untitled1.png  

  10. #10
    Ngày gia nhập
    06 2012
    Bài viết
    12

    Rất hay bạn ah. Phải thử gấp cho nóng
    Wap tai game dien thoai,tai game mien phi cho dien thoai, truy cập Hotgamevn.org để trải nghiệm thế giới game mobile hoàn toàn miễn phí

Các đề tài tương tự

  1. Tạo database có cấu trúc, sp,trigger giống hệt 1 data đang tồn tại trên Server?
    Gửi bởi billsang trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 2
    Bài viết cuối: 27-10-2011, 12:18 PM
  2. MS SQL với C# Backup trên Server A và Restore ở Server B cùng cấu trúc CSDL như thế nào?
    Gửi bởi snake_programmer trong diễn đàn Thắc mắc Microsoft SQL Server & Microsoft Access
    Trả lời: 1
    Bài viết cuối: 23-08-2011, 09:19 AM
  3. MS SQL với C# Tạo 1 trigger trên table categories kiểm soát việc xóa dữ liệu
    Gửi bởi ohlala_gaikia trong diễn đàn Thắc mắc Microsoft SQL Server & Microsoft Access
    Trả lời: 3
    Bài viết cuối: 17-01-2011, 02:46 PM
  4. Lập trình Socket trên C++ có thể giao tiếp chương trình Java trên Server được ko các
    Gửi bởi jacobkruse trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 3
    Bài viết cuối: 18-11-2010, 11:10 PM
  5. Trigger trong MS SQL server 2005!!! Cần giúp đỡ
    Gửi bởi phamhaiit26 trong diễn đàn Thắc mắc Microsoft SQL Server & Microsoft Access
    Trả lời: 1
    Bài viết cuối: 18-04-2010, 09:38 AM

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn