Vì sao nên tránh viết SQL code trong ứng dụng

Vũ Huy Tâm

Trong ứng dụng khi cần tương tác với database, có lẽ một cách làm rất phổ biến là tạo lập một chuỗi chứa lệnh SQL, ghép các giá trị  nhập vào của người dùng thành một lệnh SQL hoàn chỉnh, rồi thực hiện chuỗi lệnh SQL đó. Như ví dụ dưới đây:

string cmdStr = "INSERT INTO Customer(Name, Address, Email, Phone) VALUES('" + txtName.Text + "', '" + txtEmail.Text + "','" + txtPhone.Text + "')";
conn.Open();
SqlCommand cmd = new SqlCommand(cmdStr, conn);
cmd.ExecuteNonQuery();

Cách làm này có ưu điểm tiện lợi, giúp quá trình phát triển code nhanh (không phải chuyển qua lại giữa Visual Studio và Management Studio). Tuy nhiên nó tiềm ẩn rất nhiều vấn đề (cách làm tối ưu là viết một thủ tục trong database rồi từ ứng dụng gọi thủ tục này và truyền các tham số cho nó):

1. An ninh: việc viết lệnh SQL thẳng trong ứng dụng như vậy sẽ tạo ra lỗ hổng SQL injection, tức là hacker có thể khéo léo nhập thẳng vào trường text một chuỗi có chứa đoạn lệnh SQL và để cho database sẽ thực hiện đoạn lệnh đó. Ví dụ, khi hacker nhập vào trường txtPhone giá trị:

123');delete from order--

thì đoạn lệnh mà ứng dụng gửi cho SQL Server sẽ là:

INSERT INTO Customer(Name, Address, Email, Phone) Values('','','123');delete from order--')

Chú ý là hacker cố tình đưa hai dấu gạch ngang "--" vào cuối để biến toàn bộ đoạn ký tự phía sau thành đoạn giải thích. Kết quả là SQL Server sẽ thực hiện hai lệnh, "INSERT INTO Customer…" và "delete from order", và bảng order bị xóa sạch. Tương tự hacker có thể đưa vào các lệnh khác như "drop table order" để xóa hẳn bảng khỏi database, hoặc "select * from user" để lấy hết thông tin tài khoản của người dùng.

Nếu dùng thủ tục thì vấn đề hoàn toàn bị hóa giải, vì toàn bộ giá trị của trường text sẽ được lưu vào cột tương ứng trong bảng bên trong database. Khi đó chỉ có một lệnh INSERT được thực hiện và giá trị của Phone của bản ghi mới sẽ là "123');delete from order--"

 

2. Hiệu năng (performance): cách làm trên sẽ dẫn đến mỗi lần thực hiện SQL Server sẽ biên dịch lại câu lệnh. Khi SQL Server nhận được một câu lệnh, nó sẽ kiểm tra xem câu lệnh này đã có kế hoạch thực thi lưu trong cache hay chưa. Nó băm (hash) câu lệnh để chuyển thành một con số và đối chiếu với bảng băm trong cache, nếu tìm thấy có nghĩa là câu lệnh này đã thực hiện trước đó rồi và SQL Server dùng luôn kế hoạch thực thi đã có sẵn. Nếu không tìm thấy có nghĩa đây là câu lệnh mới và SQL Server sẽ biên dịch, tạo kế hoạch thực thi, lưu vào cache, và thực hiện câu lệnh. Vì với hàm băm, câu lệnh chỉ cần khác đi một chút (chỉ cần thêm một dấu cách) là đã cho số băm khác nhau, nên với mỗi giá trị người dùng nhập vào sẽ tạo thành một câu lệnh mới và SQL Server lại phải trải qua các bước biên dịch, tạo kế hoạch thực thi, lưu vào cache trước khi tiến hành thực hiện câu lệnh.

Trong nhiều trường hợp, chi phí cho các bước kể trên có thể rất lớn. Ví dụ với một câu lệnh mất 100 mili giây để biên dịch trong khi cũng mất 100 mili giây để thực hiện, thì chi phí để thực hiện câu lệnh này bị tăng gấp đôi. Một hậu quả khác là mỗi lần biên dịch thì kế hoạch thực thi mới sẽ chiếm chỗ trong cache, trong khi kích thước của cache chỉ có hạn. Đến một lúc kế hoạch thực thi của các câu lệnh khác sẽ bị loại khỏi cache để giải phóng chỗ, và đến khi các câu lệnh khác đó được thực hiện thì lại cần biên dịch lại. Như vậy hiệu năng của toàn bộ hệ thống bị giảm.

Khi dùng thủ tục thì tình huống sẽ thay đổi hẳn, vì SQL Server chỉ băm câu lệnh gọi đến thủ tục mà bỏ qua các tham số, cho nên khi đã thực hiện EXEC Proc1 @param=1 thì đến khi gặp EXEC Proc1 @param=2 SQL Server không cần biên dịch lại thủ tục nữa.

 

3. Bảo mật: Khi ta viết thẳng lệnh SQL vào ứng dụng như trên thì user được dùng để kết nối vào database (trong connection string) cần phải có quyền INSERT vào bảng. Thông thường các ứng dụng có đủ các thao tác đọc/ghi/xóa vào database, cho nên user trên cũng đòi hỏi đủ các quyền SELECT/INSERT/UPDATE/DELETE vào các bảng trong database. Khi hacker chiếm được quyền truy nhập vào database với user trên, hắn ta có thể mặc sức tung hoành làm bất cứ điều gì hắn muốn trong database.

Khi dùng thủ tục thì user không cần bất cứ quyền nào trực tiếp trên bảng, user chỉ cần quyền thực thi thủ tục và khi chạy thì thủ tục thực hiện các thao tác trên bảng cho user. Ta có thể dỡ bỏ hết các quyền của user trên tất cả các bảng và chỉ cấp quyền thực thi trên các thủ tục cần thiết. Ta cũng có thể đồng thời dỡ bỏ quyền truy nhập vào các bảng hệ thống, cho nên nếu hacker có truy nhập được vào database thông qua user trên, hắn ta sẽ mù tịt không biết database có các bảng nào để mà phá.

Nếu hắn truy nhập được vào mã nguồn của ứng dụng thì có thể biết được tên của các thủ tục được dùng trong ứng dụng và chạy các thủ tục này, nhưng mức độ phá hoại của hacker bị khống chế ở mức thấp hơn nhiều so với khi user có đủ các quyền.

 

4. Bảo trì: thường có những đoạn lệnh SQL được dùng lại ở một vài nơi khác nhau trong ứng dụng, hoặc thậm chí ở các ứng dụng khác nhau truy nhập chung vào một database. Khi viết thẳng SQL code trong ứng dụng ta sẽ phải viết lại đoạn lệnh trên ở tất cả những nơi nó được dùng. Điều này đã phạm vào lỗi "lặp lại code" (duplication of code) trong phát triển phần mềm. Khi cần phải sửa lại câu lệnh SQL trên (vì lỗi hoặc cần viết theo cách tối ưu hơn, hoặc cấu trúc database thay đổi dẫn đến cần viết lại) ta sẽ phải tìm đến tất cả các nơi có dùng câu lệnh SQL đó để sửa.

Với thủ tục thì ta chỉ cần sửa ở một nơi và nó có tác dụng cho toàn ứng dụng. Giống như .net tách mã chương trình ra khỏi mã html, dùng thủ tục cũng tách mã SQL ra khỏi mã chương trình. Lúc đó thủ tục có chức năng như là cổng truy nhập, hay API, mà qua đó ứng dụng giao tiếp với database. Nó tạo thành một lớp ngăn cách giữa ứng dụng và database, và che dấu toàn bộ cấu trúc database khỏi ứng dụng. Ứng dụng không cần biết database gồm có những bảng gì, mỗi bảng có các cột nào, hay các bảng quan hệ với nhau ra sao. Vì thế ta có thể dễ dàng thay đổi cấu trúc của database khi cần và sửa lại các thủ tục có liên quan mà không ảnh hưởng gì đến ứng dụng.

 

Kết luận: Việc viết mã SQL trong ứng dụng có rất nhiều vấn đề như đã chỉ ra. Với những ứng dụng nhỏ hoặc ứn dụng có những đặc thù nhất định, những vấn đề trên có thể không bộc lộ hết ra, nhưng khi ta quyết định chọn phương pháp này thì cũng cần ý thức được những hệ quả có thể xảy ra của nó. Có những trường hợp ta không muốn lưu mã nguồn trong database, ví dụ để ứng dụng có thể dễ dàng chuyển đổi giữa các hệ CSDL khác nhau. Khi đó ta bắt buộc phải viết SQL code trong ứng dụng, nhưng để giảm nhẹ các vấn đề của nó, ta nên dùng chuỗi SQL có tham số (dùng cmd.Parameters.Add) để tránh được lỗi SQL injection và biên dịch lại câu lệnh (điểm 1 và 2 ở trên). Còn khi ta có lựa chọn dùng thủ tục thì nên áp dụng phương pháp này. Đây là phương pháp mà Microsoft khuyến cáo khi viết ứng dụng trên môi trường phát triển của họ.




58 Comments

Các bài viết tương tự

Comments
  • tuyentc (16/09/2010 5:20 pm)

    Bài biết thật sự hay! em được học SQL server rồi nhưng mơi chỉ cơ bản, những kiến thức này thật hay. Cảm ơn sqlviet.com. Có bài mới gửi qua mail giúp em với. em nghĩ nên có một form đăng ký nhận bài viết mới trên blog.

  • Vũ Huy Tâm (17/09/2010 4:50 am)

    Cám ơn bạn đã có lời khen. Tôi cũng đang tìm một plugin để làm đăng ký nhận email. Nếu bạn biết cái nào dùng tốt thì chỉ cho tôi với.

  • khoaba (18/09/2010 10:12 pm)

    Cảm ơn bạn. Bài viết khá hay, dùng lệnh trực tiếp trong code theo mình những người mới lập trình hay dùng. còn những người có kinh nghiệm thì toàn dùng Store và Trigger thôi

    ———————————
    http://khoaba.wordpress.com

  • Đức Anh (23/09/2010 6:42 am)

    Bài viết rất hay và bổ ích :d thanks anh Huy Tâm nhiều

  • H2o (12/11/2010 7:44 pm)

    Mình được khuyến cáo về vấn đề này nhưng mà không rõ lắm về nguyên nhân. Nay nhờ bạn mình đã biết rõ tại sao và có thể linh động hơn cho các trường hợp.

    Nhân tiện cho mình hỏi nếu khi cần tìm dữ dạng IN thì mình nên viết thủ tục như thế nào. Ví dụ tìm tất cả Phiếu xuất của nhiều kho một lúc. Người toàn phải dùng "WHERE KhoID In (" + ListKhoIDSelect + ")" không ah. Không nghĩ ra cách viết store

  • anh (18/11/2010 6:59 pm)

    bài viết này bổ ích lắm bạn, mong ngày càng có thêm nhiều bài viết đi sát thực tế như thế nyaf hơn nữa

  • oattao (14/03/2011 7:23 pm)

    Rất hay và bổ ích. Rất cám ơn bạn đã nhiệt tình chia sẻ kiến thức.

  • daivt (17/03/2011 1:27 am)

    Bài viết rất hữu ích, cảm ơn bạn đã chia sẻ kiến thức !

  • goku (27/07/2011 11:37 pm)

    Cái nào cụng có điểm mạnh và yếu cả thôi.

    1, Viết code thẳng vào ứng dụng
    - Chạy nhanh hơn so với gọi từ procedure

    2, Viết code vào procedure
    - Phát triển rể dàng hơn

    * Còn về bảo mật thì như nhau cả thôi cái chính là do người code có biết cách sử lý chuỗi đầu vào hay không thôi.

    • Hoang Tung (31/07/2011 5:10 am)

      @goku: Bạn chắc mới học lập trình hoặc học nhưng chưa hiểu gì về 2 khái niệm biên dịch và thông dịch.

      Viết Stored Procedure (SP) là quá trình biên dịch trước các câu lệnh SQL nên tốc độ chạy thực thi nhanh hơn quá trình thông dịch các câu lệnh được gửi lên từ ứng dụng (Điều này trong mục 2 tác giả đã trình bày rất rõ )
      Nếu nói như bạn thì câu lệnh i++ sẽ thực thi giống câu lệnh i=i+1;

      Trong bài viết tác giả có đề cập về 4 vấn đề tôi đều rất đồng tình.
      Tôi xin bổ sung chi tiết thêm phần 4 (Bảo trì ), đó là khi tách nghiệp vụ ra đặt ở CSDL thì trong quá trình hoạt động của ứng dụng, nếu khách hàng muốn nâng cấp hoặc thay đổi các nghiệp vụ, nếu sự thay đồi không quá phức tạp( chỉ thay đổi trong công thức tính toán, không phụ thuộc, hoặc chịu ảnh hưởng bởi các control trên giao diện nhập, hoặc chịu ảnh hưởng ít chủ yếu dùng trên giao diện xuất ) thì việc sửa các SP đem lại giá trị kinh tế to lớn cho nhà phát triển. Vì bạn không cần phải lấy source code ứng dụng ra sửa lại các câu lệnh SQL sau đó biên dịch lại thành chương trình cài đặt, đem cài đặt cho khách hàng. Bạn chỉ cần làm 1 thao tác đơn giản là chỉnh sửa lại SP của mình.
      Một điểm nữa, khi sử dụng SP thì việc phối hợp tính toán khi yêu cầu phải có các transaction hoặc cần sử dụng đến trigger sẽ dễ dàng hơn code trực tiếp vì không phải tất cả các ngôn ngữ lập trình đều hỗ trợ trong việc coding xử lý theo batch hay transaction.
      Điều cuối cùng là đối với những truy vấn phức tạp thì viết code trực tiếp trong ứng dụng là bất khả thi. Tôi đã từng viết 1 đoạn code truy vấn trích xuất dữ liệu lên 1 báo cáo, cần đến 4 trang SP, khi đó viết code trên ứng dụng chỉ cần gọi tên SP, điều đó là vô cùng tuyệt vời thay vì viết 4 trang code đó lên ứng dụng :(
      Nhiều bạn mới lập trình nghĩ rằng không có sự khác biệt, vì những câu truy vấn của các bạn quá đơn giản nên so với viết trực tiếp và viết SP bạn cảm thấy viết SP thật rắc rối và phức tạp. Nhưng cho dù lượng code xử lý có ít thì xin nhắc lại SP thực thi vẫn nhanh hơn rất nhiều trong việc bạn gửi lên thông dịch (như đã đề cập), và nhất là với các ứng dụng đa người dùng thì khi đó bạn mới thấy được những điều tác giả đã viết thật sự hữu ích.
      Trong bài viết tác giả có phần kết luận tôi cho rằng không nhiều những người làm code đã tường minh. Nhiều người phát triển ứng dụng khi nhận ra sự mạnh mẽ trong việc sử dụng SP, view và trigger đã tách phần nghiệp vụ xử lý đặt ở CSDL nên khi ứng dụng muốn nâng cấp chuyển sang 1 hệ csdl mới điều này thực sự gặp vấn đề.
      Cuối cùng rất cám ơn tác giả vì những chia sẻ trong bài viết.

  • Mr.Tét (12/08/2011 1:31 pm)

    Chào bạn Hoàng Tùng.
    Mình nghĩ bạn goku nói cũng không hẳn sai đâu (Có thể bạn ấy nói ngắn gọn và bạn cho là chưa có kinh nghiệm) tôi xin được diễn giải một chút vì tôi cũng có cái nhìn tương đối giống GOKU.

    Thực sự mỗi cách đều có cái hay và cái dở của nó. Có thể các query dài (các truy vấn dữ liệu phức tạp) thì cần tới sp để giải quyết dễ dàng hơn.

    Nhưng hiện nay theo tôi được biết, nhiều mô hình lập trình đã có thể xử lý được rất nhiều trên code, thay vì xử lý dưới dạng storeprocedure.
    Viết sp có tính chất mềm dẻo, nhanh, abc,xyz tôi không phủ nhận.Bởi ngày đầu tôi học lập trình tôi cũng biết được điều đó.

    Nếu bạn viết trực tiếp code(và gọi store cũng vậy) thì tôi thấy rằng đó sẽ là thảm họa cho các hệ thống lớn (hệ thống của tôi hiện tại trên 10tr bản ghi/bảng và db tầm 60GB – sqlserver 2008) bởi mỗi câu query sẽ chiếm rất nhiều CPU của db server để xử lý.

    Vậy khắc phục tình trạng này như nào? Đương nhiên rồi không phải cứ cần truy vấn là phi vào db lục tung nó lên mà cái quan trọng là áp dụng giải thuật sao cho khôn khéo – thường thì mình biết dữ liệu của mình như thế nào? Phân hoạch nó ra sao để truy vấn ? Và quan trọng nữa tôi đã test. Cùng 1 query nếu tôi viết trên code, tôi có thể chạy nhanh hơn trên StoreProcedure và mô hình lập trình ở đây tôi muốn nói tới ORM. Cụ thể tôi dùng NHibernate.

    Việc tương tác dữ liệu rất nhàn (hiện tôi áp dụng cho các project dùng MSSQL và ORACLE đều không vấn đề gì).

    Hiện tại các ngôn ngữ lập trình cũng đã hỗ trợ cho lập trình viên một số mô hình để có thể tối ưu hóa việc truy cập CSDL.

    Tôi muốn chia sẻ cùng các bạn một số công cụ(tạm gọi thế) có thể sử dụng khi lập trình tương tác với DB.

    1. SubSonic (cái này cho lập trình viên .NET và MSSQL rất ngon, gen 1 phát cả store và Table lên code. Nó sẽ giúp ta tự quản lý kết nối tới CSDL)
    2. NHibernate (Khỏi bàn, thằng này cũng sinh được code .NET, gen cả db lên code và áp dụng được cho cả ORACLE và MSSQL (ngoài ra còn cả MySQL …)
    3. Linq2Sql (cái này có sẵn trong Visualstudio 2008 trở lên code dễ dàng, thích bảng nào thì kéo vào rồi truy vấn thêm. sửa. xóa ngon.

    Trên quan điểm cá nhân, tôi cho rằng tùy theo tính bảo mật của ứng dụng mà mình chọn cách tổ chức chương trình cho hợp lý. (Nếu như bạn sửa DB được thì các Lập trình viên khác cũng sửa được => Không hẳn đã là hay nhất là khi ứng dụng thương mại, bạn muốn che dấu thuật toán và nhiều hơn thế …)

    • Vũ Huy Tâm (10/01/2012 12:19 pm)

      “Và quan trọng nữa tôi đã test. Cùng 1 query nếu tôi viết trên code, tôi có thể chạy nhanh hơn trên StoreProcedure và mô hình lập trình ở đây tôi muốn nói tới ORM. Cụ thể tôi dùng NHibernate.”

      Tôi không thấy có lý do gì để stored proc chậm hơn Hibernate, chỉ có thể ngược lại. Hoặc trong điều kiện tối ưu thì bằng nhau. Bạn Mr Tét có thể nói rõ hơn.
      Vai trò của ORM rất lớn trong rapid development, nhưng tôi cho rằng nó không đối nghịch với việc viết code trong stored proc.

    • Nguyễn Quang Hiệp (21/11/2012 12:33 am)

      Tôi đồng tình với ý kiến của bạn Mr.Tét …
      Tôi làm java, không làm thiên về .NET …
      Tôi nghĩ RDBMS là thứ chúng ta đều phải sử dụng…
      Bên java chúng tôi khá kị viết hàm nghiệp vụ vào store procedure. Do các nguyên nhân như bạn đã nêu ra … ngoài ra còn thêm vài nguyên nhân nữa:
      - Khi viết NTier, tầng business mới là xử lí nghiệp vụ, là nơi cài đặt thuật toán … DB suy cho cùng chỉ là nơi lưu trữ và truy cập dữ liệu … không phải nơi xử lý nghiệp vụ….
      - Giảm tính khả chuyên khi bạn chuyển đổi và cài đặt ứng dụng trên nhiều loại RDBMS khác nhau.
      - Giảm khả năng xử lí phân tán ở tầng Business… có thể bạn cho là SP chạy nhanh, nhưng với lưu lượng request lớn, bạn vẫn chỉ có 1 máy xử lí request … còn khi viết ở code, ta có thể cài đặt vào nhiều máy khác nhau -> giảm tải cho 1 máy (vd: EJB ).
      - Viết ở SP có thể tận dụng khả năng pooling connection không? theo tôi là không … cái này dân Java rất quan tâm khi làm việc với hệ thống dữ liệu lớn đổ về DB …

      -> Đương nhiên, điều đó đúng với hệ thống multi server thôi … và tôi nghĩ là nói tới hệ thống lớn thì không phải là hệ thống chạy trên 1 server …

    • Vũ Huy Tâm (26/11/2012 4:00 pm)

      @Hiệp: Java là ngôn ngữ/nền tảng phát triển ứng dụng giống như .Net, việc giao tiếp với database không có gì khác nhau nhiều. Nên các best practice giành cho java và .Net cũng giống nhau thôi (tôi nói các best practice trong vấn đề làm việc với database). Trở lại các điểm của bạn:
      1. xử lý nghiệp vụ ở tầng business: tùy theo loại tính toán mà bạn cần
      a) nếu xử lý đòi hỏi nhiều CPU mà không cần đến truy xuất dữ liệu, đúng là nên để ở ngoài database vì nó không phải là thế mạnh của database server, và có thể SQL chưa chắc đã là ngôn ngữ thích hợp. Những xử lý kiểu như validate dữ liệu nhập vào theo những business rule phức tạp, hay tính toán khả năng 2 người trên facebook là bạn của nhau… SQL Server cũng giành riêng 1 loại hàm kiểu này (CLR function) để lưu mã .Net. Những xử lý kiểu này đúng là có thể tăng khả năng mở rộng của ứng dụng khi bạn cài business layer lên nhiều máy, vì chúng dùng CPU của từng máy.
      b) xử lý liên quan nhiều đến truy xuất dữ liệu, cái này mới là thế mạnh của SQL. Ví dụ bạn có 10 lệnh insert/update/select tất cả cần gom vào 1 transaction, và cần rẽ nhánh tùy theo kết quả của lệnh trước đó… Nếu bạn tống hết đoạn SQL code vào business layer thì hoặc là không làm nổi hoặc là cực kỳ khó khăn. Và với loại tính toán này thì cài EJB lên nhiều máy cũng không cải thiện được gì, vì tất cả các request cuối cùng đều đổ về database server. Và việc scaling up hay scaling out database server cũng không liên quan đến chuyện code ở SP hay ở business layer.
      2. tính khả chuyển sang hệ database khác: cái này tôi đồng ý với bạn.
      3. khả năng xử lý phân tán: tôi đã nói ở trên.
      4. connection pooling: Bạn hiểu sai về connection pooling. SQL Server cung cấp khả năng này và phía client (java/.net) cần khai thác được khả năng đó. Gửi nguyên 1 câu lệnh SQL hay chỉ gửi lời gọi SP cũng được pool như nhau. Còn nếu cấu hình pooling không đúng thì cũng tệ như nhau. Đây là 1 vấn đề quan trọng để tăng performance của ứng dụng, dân nào cũng cần quan tâm không riêng gì dân java.
      Nhân đọc comment của bạn, tôi cũng quay lại đọc kỹ hơn comment của Mr. Tét và một phản hồi bị bỏ lửng của tôi. Không có lý do gì code sản sinh bằng NHibernate có thể chạy nhanh hơn cùng code đó khi chạy từ SP, như tôi đã nói trong 1 comment khác ở trang này. Nếu trong thử nghiệm bạn nhận thấy như vậy là do các yếu tố khác, những sự kiện khác không liên quan đến SQL xảy ra cùng thời điểm đó.
      Ngoài khả năng chuyển đổi sang hệ thống khác, một lý do khác tôi có thể thấy viết SQL code trong ứng dụng là sự tiện lợi trong khi phát triển ứng dụng. Ví dụ bạn cần làm một loạt các thao tác đơn giản insert/update/select trên một bảng, bạn có thể viết thẳng các query này trong ứng dụng thay vì tạo ra một loạt các SP. Hoặc cả nhóm đều chuyên về phát triển ứng dụng không thạo SQL. Mr. Tét nói các framework giúp generate các SQL code giúp cho rapid development, chung qui cũng là tiện lợi. Nhưng nên nhớ, nếu bạn chọn phần nào đơn giản thì để SQL code trong ứng dụng, phần nào phức tạp thì viết SP thì chung qui bạn để SQL code ở hai nơi và không có 1 codebase hoàn chỉnh.
      Trong đợt nghỉ Thanksgiving vừa rồi, tôi có dịp ngồi với một vài người bạn cũng là dân developer ở quanh đây, làm nhiều thứ khác nhau (java, .Net, Oracle), mỗi người làm ở một industry (healthcare, wireless, media communication…). Khi bàn tán lan man sang chuyện này, tất cả đều nói nên để SQL trong SP. Đây có thể chỉ là quan điểm riêng của họ, nhưng là cách mà công ty họ đang áp dụng. Và cũng là cách công ty tôi làm.
      Tất nhiên cũng như mọi thứ khác trên đời, có nhiều cách làm để đạt cùng mục đích, và bạn không nên nhất nhất chỉ áp dụng một cách trong mọi tình huống. Trước hết bạn nên cố gắng đặt SQL code trong SP, nếu cân nhắc thấy để ở ngoài lợi hơn thì hãy để. Như bài viết này khuyên: “nên tránh” viết SQL code trong ứng dụng.

      • Nguyễn Quang Hiệp (02/01/2013 10:33 pm)

        @Tâm: Rất cảm ơn bạn về những phân tích của bạn.
        1: Với việc validate của bạn, tôi đồng tình là có thể làm trong SP với CRL Function của .NET … Nhưng vấn đề không phải dừng lại ở 1 DB: bạn phải làm việc đó trên n DB, thậm chí vừa DB – vừa Service gì đó … tôi nghĩ việc viết trong SP lúc này sẽ không còn tốt…
        Tôi đồng ý rằng maintain các validate rule trong SP sẽ dễ dàng hơn khi bạn maintain … nhưng ở tầng Business cũng có những library cho phép bạn làm việc đó rất tiện lợi.
        2: về pooling: tôi ko hiểu sai từ pooling đâu bạn, cái tôi nói ở đây ko phải chỉ là connection pool… thế này nhé, bạn có thể tạo nhiều connection tới pool -> nhiều session cùng có thể tiến hành truy cập, nhưng vấn đề khi bạn viết code trong SP: SP có Thread Safe không? nếu không thì cơ chế nào đảm bảo dữ liệu của tôi là nhất quán khi có nhiều connection cùng chạy? và nếu có, cơ chế nào khiến nó có performance cao khi chạy phải chạy đồng bộ (để đảm bảo thread safe giữa các SP được gọi), và khi đó, có còn tận dụng được thế mạnh của connection pool ko?
        3: Tôi đưa hết code vào Business Container (vd: EJB), vấn đề khó khăn không cần ngại, vì tôi sử dụng JPA (vd: Hibernate) để tạo ra câu truy vấn, tôi truy vấn trên Object – không phải trên Table -> không khó khăn. Business Container như bạn nói, gen ra nhiều đoạn code rồi đưa trở lại RDBMS, đúng là nhìn qua thì vẫn bị thắt cổ chai ở đoạn RDBMS, nhưng hãy nghĩ kĩ hơn chút nhé:
        a: bạn có thể chạy multithreading trong các transaction …
        b: bạn có thể chạy asynchronous trong các transaction với từng câu lệnh chạy song song trên các connecton khác nhau – và kết thúc khi commit …
        c: bạn có thể dễ dàng mở rộng RDBMS sang vài DB khác để cùng chịu tải (replication), ở đây tôi ko xét tới MSSQL Server – dân java tụi tôi ít khi kết nối tới MS SQL Server (và lại diễn đàn chúng ta là sqlviet có phải là sqlserverviet đâu ^_^)

        (* hỏi ngoài lề): pooling: lần trước tôi test thử khả năng pooling của SQL Server, nếu bạn đặt maxPoolSize=5 chẳng hạn, và bạn mở tới connection thứ 6, thì nó sẽ báo exception … Nếu làm trên Java với Business Container, thay vì báo exception, nó sẽ cho vào queue và tiếp tục chờ đợi connection được cấp phát (có thể set timeout). Không biết đây có phải 1 trong những yếu điểm khi làm pooling của SQL Server không?

        Tôi vẫn được khuyến cáo: nếu cần viết cái gì đó phức tạp – nhưng tần suất gọi ko quá lớn (vd báo cáo định kì …) thì hãy viết trong SP, vì như thế các engine báo cáo sẽ dễ dàng gọi hơn … SP vẫn là điều gì đó rất tiến bộ ..

      • Nguyễn Quang Hiệp (02/01/2013 10:50 pm)

        Tái bút: tư tưởng tách Code ra khỏi SP cũng khá mới, các dev trước năm 2005 bên Java tôi cũng có tư tưởng viết tất cả vào SP …
        Tôi thấy các hệ thống nguồn mở hoặc thương mại độc lập DB, họ hầu như rất ít viết SP bạn ạ…
        Cái này có thể cũng là do thói quen nữa …

      • Vũ Huy Tâm (21/03/2013 11:07 am)

        Về các điểm của bạn:
        1. Validation: Tôi hoàn toàn đồng ý rất nhiều qui tắc nghiệp vụ phức tạp có thể làm hợp lý hơn ở tầng business, tuy nhiên tôi chưa thật hiểu cái ví dụ n DB của bạn. Tùy theo việc các DB đó nằm trên cùng server hay ở các server khác nhau, việc validate ở tầng business có thể làm tăng lượng dữ liệu cần lưu chuyển (data movement) và ảnh hưởng đến hiệu năng. Tôi chia xẻ một kinh nghiệm ở công ty tôi: có một ứng dụng nhận file xml upload và thực hiện rất nhiều business rule trước khi lưu vào database. Trước đây họ slice file xml và đưa vào database rồi áp dụng các business rule ở đó, nhưng việc này ngày càng trở nên cồng kềnh. Gần đây họ thay đổi cách làm và đưa toàn bộ các business rule vào tầng ứng dụng, slice xml trong bộ nhớ và áp dụng các luật luôn ở đó. Tuy nhiên các truy vấn tới database để hỗ trợ các luật vẫn được viết qua SP (tôi không thuộc nhóm đó và không có ảnh hưởng gì tới cách họ làm, nên không định kể công trạng gì ở đây, chỉ nêu cách làm của họ như một ví dụ).
        Bạn có thể nói, viết code truy vấn ở tầng business cũng tiện lợi không kém SP, và điều này có thể đúng với rất nhiều người, nhưng nó sẽ vấp phải những nhược điểm như tôi đã nêu trong bài chủ. Quan điểm của tôi: khi có lựa chọn thì nên chọn SP.
        2. Thread safe: Khái niệm này khi vào database được chuyển thành khóa và tương tranh (lock và concurrency), được đảm bảo bởi hệ thống nhưng quan trọng là bạn phải chọn mức concurrency phù hợp và viết code hợp lý để giảm thiểu lock và tính tương tranh. SQL Server không coi trọng yêu cầu cập nhật dữ liệu đến từ nguồn nào (SP hay business, connection nào…) mà việc của nó là đảm bảo dữ liệu được toàn vẹn và lưu lượng xử lý được thực hiện tối ưu. Tôi không rỗ vấn đề cụ thể bạn nêu lên là thế nào nhưng theo tôi, việc đảm bảo thread safe ở tầng business vừa vất vả vừa kém tin cậy hơn vì ở mức độ nào đó bạn phải implement lại các cơ chế concurrency đã có trong SQL Server. Và nếu viết SQL code tệ thì nó cũng dở như nhau dù bạn đặt code ở đâu.
        3. multithreading trong transaction: Cái này tôi không tin là tạo được cải thiện gì về hiệu năng, vì phần lớn thời gian thực hiện transaction là trong database và ở trong đó thì các truy vấn vẫn được xử lý một cách tuần tự. Tôi chưa nghe nói đến một transaction chạy trên nhiều connection khác nhau, theo tôi hiểu thì không thể được, vì conccurency được đảm bảo cho từng connection mà đơn vị của concurrency là một transaction.
        Về mở rộng sang DB khác tôi cũng không thấy ưu điểm gì khi viết ở business, bạn có thể nói rõ hơn? Bạn vẫn có thể copy SP sang các DB khác. Chỉ trong trường hợp vì lý do nào đó (ví dụ an ninh), bạn cần truy cập vào DB mà không có quyền tạo code, bạn không có cách nào khác là viết code ở bên ngoài.
        Lỗi exception khi vượt quá pool size có thể không dễ chịu lắm, nhưng thực sự tôi cũng không hiểu nó có thể chứa (cứ cho là tạm chứa) connection thứ 6 vào đâu nữa nên buộc phải tạo exception.
        Theo tôi hiểu, các ứng dụng mã nguồn mở đóng gói tất các trong ứng dụng để dễ tương thích với các hệ thống database khác nhau. Các hệ thống database của các hãng khác nhau ngoài phần ngôn ngữ SQL chuẩn đều có rất nhiều mở rộng riêng cho từng hệ thống.
        Xin lỗi vì hôm nay mới nhìn thấy comment của bạn. Hy vọng cuộc tranh luận này không dẫn đến người thắng và người thua (“bên thắng cuộc” :) mà thay bằng giúp các bạn có lựa chọn đúng cho tình huống của mình

        • tung (09/02/2014 11:54 pm)

          Em đồng ý với bác tranh luận là tìm ra giải pháp tốt nhất cho từng tình huống của mình . Hiện tại project của em đang dùng Linq to Entities . E thấy khi xảy ra sự cố hoặc cần để so sánh hiệu năng của 2 câu lệnh select là rất khó khăn (phải viết vào SQL để so sánh) . Có thể trong thời gian tới em sẽ chuyển sang dạng SP . Cảm ơn bác về những phân tích trên !

  • Vo Trong Nghia (21/08/2011 5:13 am)

    bổ sung về ưu điểm và nhược điểm khi viết sql trên code và trên store:

    Đó là vấn đề bảo trì site (Maintenance), xử lý add hoc:
    1.1 viết trên code .NET khi chạy ở môi trường production thì website ở dạng published nên nếu muống chỉnh sửa thì phải dịch lại và upload lên server lại. điều này đòi hỏi bạn phải có qui trình đặc biệt tốt hoặc phải compare code khi upload lên nếu không sẽ dẫn đến tính trạng code mới lệch code cũ.
    1.2 viết trên store thì chỉ cần vô sửa store lên xong ^^__^^ simple –> thích hợp cho các khách hàng hay thay đổi y/c (nhất là các khách hàng việt nam)

  • Hoàng Thiện (09/09/2011 10:47 pm)

    Bài viết hay lắm, hữu ích và có thêm kiến thức để hack “hehehe”. cám ơn tác giả nhiều.

  • longbalan (09/01/2012 7:50 pm)

    Theo mình viết store ở trong code,vừa bảo mật lại vừa linh động.
    Kết hợp giữa 1 ngôn ngữ và sql
    Mở Visual2010\Project\Database\…
    Có bạn nào hay dùng cách này không ạ
    Hoặc một cách khác
    Mình không lưu dữ liệu trên sql nữa.lưu ra file txt hay một file mã máy để mình có thể đọc và cập nhật dưới dạng 1 (key,values)
    1Field là một file
    1Field Schema xslt,xsd để định nghĩa kiểu dữ liệu
    1Table Quan Hệ Nhiều Field(1 file)
    1Schema Quan Hệ Nhiều Table(1 file)
    1Database Quan hệ Nhiều Schema

    Về bảo mật thì
    1Cấp quyền truy cập cho file
    2Mã hóa file

    Còn quan hệ và nghiệp vụ sử lý trong code.
    (NoSQL,XSLT)
    Ý tưởng chém gió thôi
    Không biết tốc độ thế nào

    Mail:longbalan@gmail.com
    Yh:longbalan
    Nhận làm dự án web bằng java jsf,jsp,application swing,asp.net,winform
    Đặc biệt là các dự án của aptech project sem 1,project sem 2,project sem 3,project sem 4 thời hạn nhanh chóng đảm bảo tiến độ
    Rất vui làm quen với các bạn đam mê it

  • Lâm (02/03/2012 11:12 pm)

    Trời ạ!!! Lên MSDN các bạn đọc Store Procudure, người ta khuyên bạn nên lưu các T-SQL bằng Store Procedure. Bài viết này nói đúng rùi, ai mà nói lưu T-SQL trong Code ứng dụng thì nhiều vấn đề xảy ra lắm:
    - Convert một ứng dụng từ ngôn ngữ này sang ngôn ngữ khác
    - Store Procedure mặc định được tạo ra chỉ compile ở lần đầu

    • Nguyễn Quang Hiệp (21/11/2012 12:36 am)

      Đó là do MS khuyến cáo để các bạn có thể dev nhanh 1 project …
      Dòng MS mà, rất dễ học và tiện sử dụng, không quá quan tâm tới việc tương thích hệ thống RBDMS khác, họ khuyên bạn làm thế cũng là có ý đó …

  • Cuong (11/03/2012 11:42 am)

    Cảm ơn tác giả đã chia sẻ.

    + thêm ý kiến nữa là nếu các bạn viết câu SQL trong code sẽ tốn thêm tài nguyên như sau:
    1 – Tài nguyên sử dụng cho chương trình ứng dụng của bạn.
    2 – Đối với 1 câu sql phức tạp và quá nhiều dòng lệnh thì trước khi thực thi, đoạn sql này sẽ được chuyển về phía máy chủ. Các bạn cứ hình dung xem, ứng dụng của bạn sử dụng câu sql dài khoản 1 trang giấy A4 và bạn có 100 User cùng sử dụng thì câu lệnh sql mỗi lần thực thi sẽ trung chuyển qua mạng của bạn mất bao nhiêu.

  • Mr.Tét (07/04/2012 12:12 pm)

    Đây là 01 link bàn về vấn đề SP và Dynamic SQL, query trong code.

    Là một phát hiện giật mình cho anh em nào vẫn nghĩ StoreProcedure là nhanh hơn SQL trong code:

    http://d.jou.vn/Article/So-sanh-toc-do-giua-Dynamic-SQL-va-Stored-Procedures/51

    • Vũ Huy Tâm (12/04/2012 7:34 pm)

      Có mấy điểm sau có thể ảnh hưởng đến tính chính xác của thử nghiệm mà bài viết không nói rõ:
      - có clear cache sau mỗi lần thực hiện query hay không
      - thời gian thực hiện lệnh là elapsed time hay CPU time. Elapsed time thì sẽ kém chính xác vì có thể có các tiến trình khác đòi chia xẻ CPU trong lúc lệnh đang thực hiện. CPU mới là cái để so sánh tương đồng. Bài viết cũng sẽ thuyết phục hơn nữa nếu nó tách thời gian biên dịch và thời gian thực thi cho từng lệnh.

      Cho dù kết quả có chính xác thì tôi cho đây là lỗi của SQL Server hơn là 1 đặc tính. Nhận được cùng 1 câu truy vấn ở hai dạng khác nhau thì trình tự cũng phải như nhau. Câu truy vấn ở dạng gọn gàng (thủ tục) phải có ưu thế hơn. Nói nôm na như người thu tiền ở cửa hàng nhận tờ check 1 triệu sẽ thao tác nhanh hơn so với nhận một mớ 1 triệu tiền lẻ. Có thể trong tình huống trên, SQL Server khi nhận được lời gọi thủ tục đã làm thêm 1 số bước vòng vèo không cần thiết.

  • thuybeo (06/08/2012 12:32 am)

    bài viết rất hay ạ. cảm ơn a ạ

  • TrumIT (17/08/2012 8:42 pm)

    *****…NET sinh ra cái đó để tránh private khi tương tác cơ sở dữ liệu. Chả nhẽ cứ phải viết SP trong data…nó có một hạn chế rất lớn là khi chuyển đổi dữ liệu khác nhau đó.

    • Vũ Huy Tâm (17/08/2012 8:57 pm)

      nhắc nhở một lần thôi: comment còn dùng từ ngữ bất lịch sự thiếu tôn trọng người khác sẽ bị xóa tức khắc. Viết cẩn thận thì tôi còn để đây cho mọi người tranh luận

  • moho (20/09/2012 10:57 pm)

    thanks

  • moho (20/09/2012 10:59 pm)

    cho em hỏi là làm thế nào để có thể sổ xuống danh sách các tham số đã có vậy? em khog biết làm thế nào nên viết rất chậm mà là nhiều lúc không chính xác nửa. xin cảm ơn!

  • Nhân (02/11/2012 5:01 am)

    Mình vừa học sql cách đây không lâu, cho mình hỏi về vấn đề này 1 chút. Nếu như theo bài giảng này thì không nên chèn trực tiếp câu lệnh sql vào code trong ứng dụng. Vậy nếu mình search mà sử dụng câu store thì như thế nào, mình phải truyền vào tất cả các biến, nhưng nếu mình chỉ muốn search trên 1 hay 2 trường thôi thì sao, câu store sẽ không đáp ứng được nếu không truyền vào tất cả các biến

  • TonyBui (07/06/2013 12:42 am)

    Dear anh Tâm,
    Trong nội dung topic anh viết, em đang quan tâm đến mục 3 (Bảo mật).

    Theo nội dung anh viết, nếu ứng dụng của chúng ta thao tác hoàn toàn bằng Stored Procedure thì user dùng để kết nối chỉ cần phân quyền thực thi thủ tục là đủ.

    Anh có thể hướng dẫn em phân quyền cho user chỉ có quyền thực hiện thủ tục được không ạ?

    Có nghĩa là, em đã xây dựng 1 ứng dụng thao tác hoàn toàn bằng thủ tục với DB rồi.

    Anh chỉ cho em cách phân quyền tối thiểu cho user với ạ!

    Mong sớm nhận được hồi đáp của anh.

    Cảm ơn anh trước ạ!

  • Vũ Huy Tâm (07/06/2013 3:27 pm)

    để gán quyền thực thi cho thủ tục bạn chỉ cần chạy lệnh sau:
    GRANT exec ON dbo.SomeProc TO [SomeUser]

    miễn là user đó đã tồn tại trong database (có public role)

    • TonyBui (09/06/2013 9:25 pm)

      Thanks anh Tâm nhé,
      Em làm được rồi ạ.

  • november green (28/08/2013 10:30 am)

    cảm ơn rất nhiều
    bài viết rất hay

  • van cuong (06/09/2013 1:02 am)

    Chào các anh chị
    Theo mình thì dùng lệnh SQL trực tiếp trong chương trình hay viết SP tuy thuộc ngữ cảnh và khả năng của mỗi người thôi (theo chủ đề anh tâm đã đề cập…), bởi vậy việc so sánh là rất khó
    Thân chào !

  • Bonano (15/10/2013 2:42 pm)

    Đánh giá:
    Lập trình với CSDL có tích hợp viết các thủ tục xử lý như MS SQL mà lại viết code SQL trong mã nguồn ứng dụng là không chuyên nghiệp, không có hệ thống, chỉ dành cho các sản phẩm kiểu: viết để chơi, viết cho biết, manh mún, chắp vá. Dù bất cứ lý lẽ thì thì … chốt lại cách nghĩ đó vẫn chưa thoát khỏi tư duy newbie (lính mới)
    Về an ninh, bảo mật: ai bảo là 2 cách như nhau, build 1 project lớn mà không xây dựng thủ tục trong chính hệ quản trị CSDL rồi public cho mọi người biết xem có bị xé cho tan hoang không.

    Kết: cái nào nó đã có thế mạnh thì nên ( nếu không muốn nói là “bắt buộc”) dùng chính các năng lực của nó, đừng có nghĩ dựng ra 1 cái gì gì rồi bảo là giải pháp thay thế. Vì cứ cho là giải pháp thay thế đó vá được lỗ hổng nào đó mà hệ CSDL đó đang có thì đến lúc ông làm xong nó cung đã xó bản upgrade thập chí là update hoặc new version ngon hơn rùi.

    Hãy nâng tàm nhìn cao hơn để có thể tạo ra nhưng sp chuyên nghiệp, đừng luẩn quẩn với những dòng code thừa.

    Like bài viết tác giả với các đánh giá chuẩn mực mà MS từng khuyến cáo programers nhưng ít ai lưu tâm thực sự.

  • Tấn Đặng (03/07/2014 12:05 am)

    @Bonano : bạn nói thế mình cũng không đồng ý, tùy theo ngữ cảnh mà mình có thể sử dụng khác nhau. Mình hoàn toàn đồng ý vấn đề sử dụng store-procedure sẽ nhanh hơn excute sql từ code (cái này là miễn bàn). Vấn đề nhìn nhận bây giờ là tùy theo ngữ cảnh nào mình sẽ sử dụng cách tương ứng, 1 ứng dụng viết ra em đảm bảo không ai có can đảm viết store 100% đặt trên database cả, 1 số thứ vẫn phải làm ở tầng business (mặc dù store có thể làm tốt hơn). Các bạn thử nghĩ tất cả xử lý đặt lên store, ai đó chỉ cần copy database là về có thể làm 1 ứng dụng khác na ná theo mà không cần tốn nhiều công sức như tác giả. Em thấy chỉ sử dụng store khi các process cần xử lý nhiều data hoặc tần suất sử dụng lớn thôi, còn core xử lý vẫn ở business. Còn như bác Bonano nói ai sử dụng code SQL là newbie thì cần nhìn nhận lại, bác mổ xẻ cái MS Dynamic CRM to đùng ra xem, store nó vẫn sử dụng rất hạn chế, tất cả nó build thành DLL hết, và khi cần excute dynamic sql thì nó sử dụng sp_executesql.

  • nguoihanoi (05/07/2014 12:54 am)

    Tất cả những gì liên quan đến dữ liệu như truy xuất sửa đổi, nên dùng stored procedures. Tất cả những gì không liên quan đến dữ liệu, như các thuật toán, logic đặc trưng của ứng dụng thì nên để trong ứng dụng.

    Các câu lệnh SQL để truy xuất và sửa đổi mà để trong các class của Java/C# hay tạo bởi các anh như EJB, thì chỉ tổ tạo công ăn việc làm cho những thằng đấm bóp dạo như tui :) Cám ơn trời, ở ta chẳng hiểu sao số này cũng kha khá.

    Còn bảo rằng viết SQL trong ứng dụng giúp dễ dàng hơn khi chuyển đổi hệ thống cơ sở dữ liệu, như SQL Server sang Oracle hay ngược lại, thì đúng là lạc quan tếu. Tui thường xuyên gặp những chuyện này trong quá trình đi kiếm cơm. Nhiều anh trưởng phòng kỹ thuật phán tỉnh rụi : trình độ thiết kế cơ sở dữ liệu nằm ở chỗ thiết kế làm sao để dễ dàng chuyển đổi từ hệ thống CSDL này sang CSDL khác. Tui hỏi : chắc anh đã làm qua nhiều loại hệ thống CSDL rồi nhỉ. Anh đáp : tôi chưa làm Oracle nhưng tôi biết các loại CSDL cũng gần gần như nhau cả thôi. Ghê quá, CSDL mà cứ như là cave, cái nào cũng gần gần giống nhau :)

    • Red Devilic (08/07/2014 2:42 am)

      =)).

      DML thích thì để trên ứng dụng cũng được, code nhàn hơn nhưng sau có vấn đề thì DB lại không nhàn.
      Còn Report thì default nên xài sp hoặc func.

      Trừ các loại Dynamic Report thì để đâu cũng như nhau :(

    • nhut truong (17/05/2015 3:24 am)

      mình không vô để bình luận, vì tôi đọc comment của bạn thích tính cách của bạn, mong mot ngay nào đó dc làm chung..:D

  • nguoihanoi (08/07/2014 9:22 pm)

    Chào bác Đỏ

    Cái đề tài này sinh ra từ thời tui còn lầm tưởng DB có nghĩa là … đánh bạc :) Thế mà giờ lôi lên, thấy thẹn. Nhưng phải nói là thiên hạ ngoài kia vẫn đang cãi nhau về đề tài này, nên có lạm bàn không đầu không đũa….

    DB quá phức tạp, nhất là chưa hoàn thiện, và mỗi hệ thống có 1 cách giải quyết khác nhau. Nên thiết kết db ở hệ thống này có thể không chạy tốt ở hệ thống khác và ngược lại. Chuyển đổi hệ thống là việc chẳng đặng đừng, và rất ít thành công, cho những db lớn và phức tạp.

    Hãy xét 1 trong những ví dụ đơn giản nhất.

    select * from HoaDon where ngayBanHang=’hom nay’.

    Câu lệnh loại này chắc chắn được sử dụng rất nhiều trong thực tế, nhưng có mấy anh tự hỏi nó hoạt động như thế nào.

    Có anh sẽ quát : vớ vẩn, chẳng lẽ phải biết hoạt động của xe máy mới nên chạy xe máy hay sao? Quan trọng là biết nó trả về dữ liệu là được, còn chuyện nó hoạt động như thế nào để lấy đúng dữ liệu là chuyện của hệ thống, biết để làm gì?

    Tiếc là nó lại chẳng vớ vẩn và ngay các anh đã có thể tự mâu thuẫn chứ chưa cần đến hệ thống.

    Giả thử bảng HoaDon có triệu dòng.

    Tại thời điểm 11:00:00, có 1000 dòng với ngayBanHang=’hom nay’.
    Tại thời điểm 11:00:10, có 1020 dòng với ngayBanHang=’hom nay’.

    Lúc 11:00:00, anh chạy câu lệnh

    select * from HoaDon where ngayBanHang=’hom nay’

    Câu lệnh chạy hết 10 giây.

    Tức nó sẽ trả dữ liệu về lúc 11:00:20.

    Vậy anh muốn nó trả về bao nhiêu dòng, 1000 hay 1020 ? Chắc chắn nhiều anh sẽ giật mình : hóa ra lâu nay mình không hề nghĩ đến chuyện này.

    Có anh bảo trả về 1000 mới đúng vì đó là thời điểm câu lệnh bắt đầu chạy, nhưng cũng nhiều anh bảo trả về 1020 mới đúng vì đó là thời điểm nhận được dữ liệu. Thậm chí có anh hôm nay bảo thế này ngày mai lại bảo thế khác. Ở đây chỉ là ý muốn của anh, không có chuyện đúng-sai, anh muốn thế nào cũng được, nhưng phải nhất quán, và phải kiểm tra xem ứng dụng của mình có hoạt động với khái niệm đúng-sai trong trường hợp này.

    Thế đấy, mới chỉ là ý muốn chủ quan của anh thôi mà đã rắc rối. Bây giờ thì nói chuyện hệ thống. Anh muốn thế nào là 1 chuyện, hệ thống trả về như thế nào là chuyện khác.

    Với trường hợp trên, hệ thống trả về bao nhiêu dòng, 1000 hay 1020 ? Câu trả lời có thể làm ngạc nhiên nhiều anh : có thể 1000, có thể 1010, có thể 1020, thậm chí có thể 1030 dòng. Trả về bao nhiêu là trách nhiệm của các lập trình và dba trong việc thiết kế các yếu tố liên quan, và mỗi hệ thống CSDL có 1 cách thiết kế khác nhau.

    Liên kết với câu hỏi vớ vẩn ở trên, rõ ràng nó vớ vẩn vì các chính anh vớ vẩn, không biết mình đang làm cái gì.

    Tui nêu ví dụ này để nhấn mạnh 2 điều. Một là cái gì thuộc về db thì nên để trong db thông qua các store, không nên để trong ứng dụng, vì nó quản lý chúng rất rắc rối, đừng ngộ nhận vì vẻ ngoài trông đơn giản của chúng. Ngay cả để trong store thì cũng đã rắc rối lắm rồi, còn để chúng trong các ứng dụng thì cực kỳ khó quản lý, trừ khi db nhỏ, không quan trọng, hoặc không thèm quản lý.

    Hai là phản bác cái ý tưởng thiết kết db để khi cần là chuyển từ hệ thống CSDL này sang CSDL khác. Mỗi hệ thống dựa trên mỗi cái nền khác, có những điểm mạnh điểm yếu ỏ các lãnh vực khác nhau. Nếu db của anh có thể chuyển từ hệ thống này sang hệ thống khác thì db của anh đã không sử dụng điểm mạnh của cả 2 hệ thống, như thế db của anh chỉ là db văn nghệ. Như thế thì chuyển hay không chuyển các db ấy vẫn luôn tồi tệ.

    Đó chỉ là suy nghĩ của 1 thằng đấm bóp dạo. Trong thực tế rất nhiều anh cứ thảy các lệnh SQL vào Java/C#. Một hệ thống CSDL quản lý còn chưa xong mà cứ nghĩ đến chuyện thiết kết sao cho dễ dàng chuyển đổi hệ thống. Kết quả là mấy thằng đấm bóp dạo như tui có việc mà làm. Trên phương diện này, tui đồng ý nó là 1 điểm son :)

    • saleoteo (16/09/2014 5:16 am)

      anh NguoiHaNoi cho em biết nghề “Đấm bóp dạo” là sao vậy ? cảm ơn

    • tung (29/02/2016 3:24 am)

      Lâu lắm không thấy bác comment nữa. Em thấy các comment của bác rất hay và kinh nghiệm :) ))

  • NXN (09/07/2014 10:38 pm)

    bác nguoihanoi viết hay quá :)

  • Vũ Huy Tâm (10/07/2014 10:08 am)

    Trong tiếng Anh có từ “best practice” không biết dịch là gì, để chỉ các phương pháp, cách thức đã được kiểm chứng là đúng đắn và có hiệu quả cao. Viết SQL code trong stored proc là một best practice rất cơ bản trong phát triển ứng dụng.
    Một chút thanh minh cho việc chuyển đổi hệ thống: không phải ứng dụng nào cũng lớn, phức tạp, khai thác hết các giới hạn của database. Có những ứng dụng nhẹ hơn, cần phát triển nhanh trong khi vẫn muốn dùng cho nhiều hệ database khác nhau. Ngày trước công ty tôi mua một hệ thống CMS họ nói có thể chạy trên MSSQL và PostgreSQL, tùy theo khách hàng đang dùng loại nào, mở ra thấy toàn SQL code trong ứng dụng. Có thể hiểu họ chủ trương tránh không liên quan đến ngôn ngữ thủ tục của từng hệ thống (như T-SQL trong MSSQL) mà chỉ muốn tập trung vào phần SQL. Tôi đồng ý là cách làm này không tối ưu nhưng cân bằng lại có thể có lợi hơn vì giảm chi phí, không phải tìm developer biết ngôn ngữ thủ tục của các hệ thống khác nhau.

  • Sơn Gô Ku (24/07/2014 12:09 am)

    Thanks các bác nhiều lắm! Em đọc mà ngộ ra được rất nhiều điều!

  • Kiềm Kim Loại (02/12/2014 5:37 am)

    Cảm ơn bài viết của các bác. Em mới vào nghề, đi làm Oracle, đọc bài viết và bình luận của các bác mà rất hay và thiết thực!

  • Hoàng Không Béo (06/12/2014 2:36 am)

    Không phải dân lập trình mà đọc bài viết và comment của các bạn thấy thú quá !
    vui kực luôn, vãi kả làng :D

  • Carol (14/10/2016 6:39 pm)

    This site is really cool. I have bookmarked it.
    Do you allow guest posting on your website ? I can write hi
    quality posts for you. Let me know.

  • Toantv (19/10/2016 12:11 am)

    Viết code trong ứng dung, Mình thích thì mình viết thôi.
    Nếu muốn xây dung ứng dụng nhanh chóng thì viết truy vấn trong ứng dung + sử dung linq. Đây là cách nhanh nhất để làm việc với csdl.

  • HOÀNG BÁ TÙNG (14/12/2016 5:29 am)

    viết code trên visual studio va code tren sql management studio khác nhau nhu thế nào???
    em trứoc giờ không học cái này.
    nhưng giời mới vào công ty mới , sếp kêu học
    nhung em vẫn chưa hiểu viết code trên sidual studio và trên sql mânment studio khác nhau nhau như thế nào

    • HOÀNG BÁ TÙNG (14/12/2016 5:33 am)

      có ai hiểu nói cho em với.
      em chưa học đựoc nhiều nhưng cảm thấy cũng không khó lám.
      chì cần lên webside w3school.com lôi lệnh ra

      mình tạo mọi thứ như datbase , bảng , cột , dữ liệu
      song lôi ra sài. update thêm
      truy vấn các kiểu

      còn gì nữa không anh chị em nào biết chỉ vơi

    • Không hiểu (26/12/2016 7:52 am)

      Làm sao bạn đỗ được vào chỗ đó ngon vậy ?

  • Thế Tuân (10/01/2017 9:17 pm)

    Cảm ơn tác giả cùng những bạn khác đã nêu ý kiến. Mình đọc xong tiếp thu được rất nhiều :D

Leave a Reply

Hướng dẫn: Để nhập mã T-SQL bạn dùng thẻ <pre lang="tsql"> và </pre>.
Ví dụ: <pre lang="tsql">SELECT * FROM MyTable</pre>