• Làm thế nào để dùng SQL trong lập trình?
  • Làm thế nào để dùng SQL trong lập trình?

    paulsteigel > 06-05-16, 12:27 PM

    Tôi mạn phép mở ra chủ đề này và mong tất cả các bạn cùng đóng góp viết tiếp. Thực tế là có vài người bạn tôi cứ loay hoay không biết phải chuyển sang làm việc với SQL thế nào đặc biệt là khi ta mới chỉ chập chững bước vào VBA và đang quen với việc dùng Excel.


    Bài viết còn dở dang. Mong chúng ta cùng phối hợp hoàn thiện để các anh em mới vào nghề có đủ tự tin bước sang SQL với Access.
    Xin chân thành cảm ơn.
    (Tiện thể để minh chứng - xin gửi một đoạn mã chương trình liên quan đến việc thao tác với DAO/ADODB từ Excel)
    ===========================================================


    Đoạn mã sau đây làm các việc sau:
    1. Tạo CSDL theo 2 giao thức DAO/ADODB
    2. Tạo bảng dữ liệu

    và các thủ tục kết nối hỗ trợ 2 giao thức


    Mã:
    Option Explicit
    ' Duong dan den csdl
    Private dbPath As String
    ' Doi tuong de ket noi voi CSDL
    Private dbObject As Object

    ' Const for ADODB
    Private Const Jet10 = 1
    Private Const Jet11 = 2
    Private Const Jet20 = 3
    Private Const Jet3x = 4
    Private Const Jet4x = 5

    ' Const for DAO
    Private Const dbVersion10 = 1
    Private Const dbVersion11 = 8
    Private Const dbVersion20 = 16
    Private Const dbVersion30 = 32
    Private Const dbVersion40 = 64

    ' Cach thuc ket noi
    Private ConnectByADODB As Boolean

    Sub LoadForm()
        ' Mo form ra nao
        frmSearch.Show vbModal
    End Sub

    Sub CreateDb()
        ' Khoi tao CSDL Access
        dbPath = ThisWorkbook.Path & "\Data.mdb"
            
        ' Kiem tra xem CSDL da co khong, neu co thi xoa di
        If FileOrDirExists(dbPath, True) Then Kill dbPath
        
        'Tao CSDL phien ban Access 2000 (ho tro Unicode)
        If Range("dbType") = "DAO" Then
            ' Dung DAO
            CreateDbDAO dbPath
        Else
            ' Dung ADO
            CreateDbAdo dbPath
        End If
        
        ' Khoi tao cac bang so lieu
        CreateTable
        
        ' Them so lieu vao cac bang
        AddData2Table
        
        ' Dong CSDL
        dbObject.Close
    End Sub

    ' Them so lieu tu Excel vao cac bang trong CSDL
    Private Sub AddData2Table()
        ' Tien hanh nap du lieu bang Ma canbo
        Dim dbRange As Range, ptrCell As Range, SqlTxt As String
        Set dbRange = Range("tblCanbo")
        Set ptrCell = dbRange.Cells(1)
        While ptrCell <> ""
            SqlTxt = "INSERT INTO tblCanbo(fldMaCanbo, fldMaDiaban) VALUES('" & ptrCell & "','" & ptrCell.Offset(0, 1) & "');"
            Call ExcuteSQL(SqlTxt)
            Set ptrCell = ptrCell.Offset(1)
        Wend
        ' Tao bang dia ban
        Set dbRange = Range("tblDiaban")
        Set ptrCell = dbRange.Cells(1)
        While ptrCell <> ""
            SqlTxt = "INSERT INTO tblDiaban(fldMaDiaban, fldTenDiaban, fldDoi) VALUES('" & ptrCell & "','" & ptrCell.Offset(0, 1) & "'," & ptrCell.Offset(0, 2) & ");"
            Call ExcuteSQL(SqlTxt)
            Set ptrCell = ptrCell.Offset(1)
        Wend
        
        ' Xoa cac bien khoi bo nho
        Set dbRange = Nothing
        Set ptrCell = Nothing
    End Sub

    '======================================
    ' Phan chen so lieu vao bang thi giong
    ' nhau giua DAO va ADODB

    '-------------TAO BANG CSDL-------------
    ' Nhom cac thu tuc lam viec voi ADODB
    Private Sub CreateTable()
        Dim SqlTxt As String
        SqlTxt = "Create Table tblCanbo(fldMaCanbo Text(20), fldMaDiaban Text(20));"
        Call ExcuteSQL(SqlTxt)
        SqlTxt = "Create Table tblDiaban(fldMaDiaban Text(20), fldTenDiaban Text(255), fldDoi Long);"
        Call ExcuteSQL(SqlTxt)
    End Sub

    Private Function ExcuteSQL(SqlStr As String) As Boolean
        On Error GoTo ErrHandler
        dbObject.Execute SqlStr
        ExcuteSQL = True
    ErrHandler:
    End Function
    '================END======================

    '======================================
    ' Nhom cac thu tuc lam viec voi ADODB
    Private Sub CreateDbAdo(FileName As String, Optional Format As Long = Jet4x)
        Dim Catalog As Object
        ' Khoi tao mot phien lam viec voi ADO
        Set Catalog = CreateObject("ADOX.Catalog")
        ' Tao csdl dang Access 2000
        Catalog.Create "Provider=Microsoft.Jet.OLEDB.4.0;" & _
         "Jet OLEDB:Engine Type=" & Format & ";Data Source=" & FileName
        Set Catalog = Nothing
        Set dbObject = CreateObject("ADODB.Connection")
        
        ' Mo CSDL
        dbObject.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & FileName & ";"
    End Sub
    '================END======================

    '======================================
    ' Nhom cac thu tuc lam viec voi DAO
    Sub CreateDbDAO(FileName As String, Optional Format As Long = dbVersion40)
        Dim Engine As Object
        Set Engine = CreateObject("DAO.DBEngine.36")
        Engine.CreateDatabase FileName, ";LANGID=0x0409;CP=1252;COUNTRY=0", Format
        
        ' Mo CSDL
        Set dbObject = Engine.Workspaces(0).OpenDatabase(FileName)
    End Sub
    '================END======================

    '======================================
    ' Khoi tao ket noi voi CSDL
    Property Get ConnectDatabase(dpPath As String, Optional ConnectAsADODB As Boolean = True) As Object
        Dim dbs As Object
        On Error GoTo ErrHandler
        If ConnectAsADODB Then
            Set dbs = CreateObject("ADODB.Connection")
            dbs.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & dpPath & ";"
            Set ConnectDatabase = dbs
        Else
            Set dbs = CreateObject("DAO.DBEngine.36")
            Set ConnectDatabase = dbs.Workspaces(0).OpenDatabase(dpPath)
        End If
        ConnectByADODB = ConnectAsADODB
    ErrHandler:
    End Property

    ' Khoi tao ket noi voi recordset -
    ' tuy thuoc vao kieu ket noi nhe
    Property Get GetRecordset(dbObj As Object, SqlText As String) As Object
        On Error GoTo ErrHandler
         
        If ConnectByADODB Then
            ' Voi ADODB, Like '*abc*' phai la '%abc%' nhe
            Set GetRecordset = CreateObject("ADODB.Recordset")
            GetRecordset.Open Replace(SqlText, "*", "%"), dbObj
        Else
            ' Voi DAO, Like '*abc*' de tim kiem
            Set GetRecordset = dbObj.Openrecordset(SqlText)
        End If
        Debug.Print GetRecordset.EOF
    ErrHandler:
    End Property

    '================END======================

    '======================================
    ' Nhom cac thu tuc lam viec voi Thu muc
    Function FileOrDirExists(PathName As String, Optional FileObject As Boolean = False) As Boolean
        'Kiem tra xem file hoac folder co ton tai hay khong?
        Dim Fso As Object
        Dim FilePath As String, lRet As Boolean

        Set Fso = CreateObject("Scripting.FileSystemObject")
        If PathName = "" Then Exit Function
        If FileObject Then
            FileOrDirExists = Fso.FileExists(PathName)
        Else
            FileOrDirExists = Fso.FolderExists(PathName)
        End If
        Set Fso = Nothing
    End Function
    '================END======================
  • RE: Từ lập trình thông thường chuyển sang SQL

    paulsteigel > 06-05-16, 12:31 PM

    (06-05-16, 12:27 PM)paulsteigel Đã viết: ==========================BÀI 1=================================
    1.Đặt vấn đề
    Nói về lập trình mà thiếu công cụ SQL thì giống như người tù đi bộ mà tay và chân đều bị xiềng xích.
    Có rất nhiều công việc liên quan đến xử lý số liệu mà để thực hiện được nhiệm vụ đơn giản phải lập trình kha khá trong khi với SQL chỉ cần thực hiện một lệnh truy vấn.
    Hãy lấy một ví dụ: Có một danh sách khách hàng trong đó tên khách hàng có thể bị trùng nhau. Yêu câu lấy danh sách khách hàng không bị trùng. Danh sách khách hàng có 2 cột: Số thứ tự và Tên khách hàng trong bảng Danhsach
    Có 2 cách giải:
    ·        Cách 1 thuần về lập trình ta làm như sau
    + Duyệt qua từng khách hàng trong danh sách
    + Tạo môt mảng phụ/ biến phụ để lưu khách hàng đầu tiên
    + Kiểm tra với khách hàng thứ 2 nếu trùng thì bỏ qua và chuyển tiếp, nếu không trùng thì lưu vào mảng phụ/ biến phụ;
    + Chuyển qua khách hàng thứ 3 và so sánh với các tên có trong mảng phụ, nếu không có thì thêm tiếp, nếu có rồi thì bỏ qua và chuyển sang khách hàng tiếp theo.....
    Chỉ như vậy cũng mệt nhoài với một số anh chị mới làm quen với lập trình, nhiều khi phải mất hàng tiếng đồng hồ.
    ·        Cách 2: Dùng SQL
    Để lấy được danh sách nói trên ta chỉ cần chạy 1 truy vấn
    “Select distinct [Tên khách hàng] From [Danhsach];”
    Và đã có ngay kết quả.
    Như vậy ta có thể thấy SQL giúp cho cuộc sống của dân lập trình dễ dàng hơn rất nhiều, đặc biệt là các bạn làm việc nhiều với tổ chức Cơ sở dữ liệu.

    2.Các bước chuẩn bị
    Bản chất SQL là các tập lệnh và chỉ thực thi được nếu ta có bộ công cụ nhận lệnh hay nói khác hơn là Database Engine (DBE – Trình quản trị CSDL) và VBA thao tác với Cơ sở dữ liệu thông qua Database Engine.
    Có nhiều loại DbE khác nhau nhưng xin phép được gọi tên 2 loại khá phổ biến đó là DAO và ADO (sau này là ADODB).
    Để làm việc được với SQL trong môi trường thiết kế VBA, ta cần phải có một số chuẩn bị sau đây:

    2.1.Bước 1: Tạo lập kết nối với DbE
    Cách 1: Kết nối sớm – Early bind
    Kết nối này có thể thiết lập được thông qua việc đặt tham chiếu Refercences của Dự án VBA (VBA Project) bằng cách nhấn Tools/References và chọn Microsoft DAO (phiên bản mới nhất là 3.6) hoặc Microsoft ActiveX Data Objects  (chọn 1 trong các phiên bản 2.0 đến 6.1).
    Sau đó khởi tạo kết nối với các đối tượng của bộ thư viện DAO hoặc ADODB thông qua khai báo các biến.
    Cách 2: Kết nối muộn – Late bind
    Dùng các câu lệnh khởi tạo kết nối với 1 trong 2 loại đối tượng trên bằng câu lệnh CreateObject. The cách này bạn không cần phải thiết lập References tới 1 trong 2 đối tượng như nói ở trên.
    Thứ tự tạo kết nối bao giờ cũng phải có 2 việc sau:
    + Tạo kết nối với trình quản trị (DbEngine, Database, Connection): Đây là trình cho phép ta thao tác với bảng dữ liệu và toàn cơ sở dữ liệu.

    a.   Sử dụng kết nối sớm (đòi hỏi phải thiết lập References tới các bộ thư viện – Early bind
    ·        Bước 1: Khởi tạo biến kết nối
    Với DAO: Dim dbs as Database
    Với ADODB:
    Cách 1:
    Dim dbs as ADODB.Connection
    Set dbs = new ADODB.Connection
    Cách 2:
    Dim dbs as New ADODB.Connection

    ·        Bước 2: Kết nối CSDL
    Với DAO: Set dbs=OpenDatabase(“Đường dẫn tới CSDL Access”)
    Với ADODB: dbs.Open "Provider = Microsoft.Jet.OLEDB.4.0; Data Source = Đường dẫn tới CSDL Access” & ";"

    b.   Sử dụng kết nối – Late bind
    ·        Bước 1: Khởi tạo biến kết nối
    Với DAO: Dim dbs As Object
    Với ADODB: 
    Dim dbs As Object
    Set dbs = CreateObject("ADODB.Connection")
    ·        Bước 2: Kết nối CSDL
    Với DAO: Set dbs = CreateObject("DAO.DBEngine.36")
    Với ADODB:
    Set ConnectDatabase = dbs.Workspaces(0).OpenDatabase(“Đường dẫn tới CSDL Access”)
    dbs.Open "Provider = Microsoft.Jet.OLEDB.4.0; Data Source = Đường dẫn tới CSDL Access;"

    Đến đây chúng ta đã kết nối được với Cơ sở dữ liệu và đối tượng dbs đã được thiết lập để thực hiện công việc ta cần.
    Với Access, thao tác với CSDL hiện tại ta có thể sử dụng ngay đối tượng CurrentDb (DAO) hoặc CurrentProject.Connection.
    Phần lớn các thao tác liên quan đến SQL về tạo bảng, xóa bảng, sửa đổi cột số liệu, xác lập quan hệ ...vv bổ sung số liệu đã có thể làm tại bước này với đối tượng dbs thông qua lệnh dbs.Execute “Lệnh SQL”.
    Tuy nhiên để thao tác trực tiếp với các bản ghi thì cần nắm được bước 2 nữa.

    2.2.Bước 2: Thiết lập kết nối với bảng số liệu (nếu cần)
    Cả DAO và ADODB đều có đối tượng RecordSet để đại diện cho bảng số liệu và chúng có các thuộc tính cơ bản giống nhau. Để làm việc với chúng, ta cần khai báo.
    Dim rcs as DAO.RecordSet hoặc Dim rcs as ADODB.RecordSet
    + Với DAO:
    Set rcs = dbs.OpenRecordset("Tên bảng cần mở hoặc câu lệnh SQL");
    + Với ADODB:
    Set rcs = New ADODB.RecordSet
    rcs.Open "Tên bảng cần mở hoặc câu lệnh SQL", dbs
    Và ta có thể thao tác với đối tượng RecordSet với các thuộc tính thông dụng nhất sau đây:

    rcs.EOF: Trả về xem con trỏ bản ghi rcs đang ở cuối bảng hay chưa. Nếu khi vừa mở bảng ra mà EOF trả về True thì có nghĩa là bảng đó không có bản ghi nào.
    rcs.BOF: Trả về xem con trỏ bản ghi đang ở đầu bảng dữ liệu hay không
    rcs.MoveNext/ rcs.MovePrevious/ rcs.MoveFirst/ rcs.MoveLast: Di chuyển sang bản ghi tiếp theo/ trước/ đầu/ cuối
    rsc.Edit/ rcs.Update: (với DAO) để chuyển vào chế độ sửa bản ghi, kết thúc việc chỉnh sửa thì dùng rcs.Update.
    Với ADODB chỉ cần dùng lệnh rcs.Update mà không cần đưa vào chế độ sửa
    rcs.Fields(“Tên trường”): Trả về hoặc gán giá trị cho 1 trường trên một bản ghi hiện tại

    2.3.Bước 3: Kết thúc làm việc với CSDL
    Một nguyên tắc bắt buộc phải tuân thủ là: Khi kết thúc làm việc với các đối tượng CSDL, phải đóng nó lại để giải phóng bộ nhớ và bỏ khóa CSDL. Đối với cả 2 loại DAO và ADODB, cách chung để thực hiện việc này là:
    Dbs.Close – để đóng Cơ sở dữ liệu
    Rcs.Close – để đóng kết nối với bảng.
    Thứ tự thực hiện là Đóng bảng trước khi đóng CSDL. Với trường hợp kết nối muộn thì cần thêm phần giải phóng biến nữa như sau:
    Set dbs=nothing và set rcs=nothing.

    3.Ngôn ngữ SQL
    Phần trên ta vừa trao đổi cách khởi động và thao tác thông thường với Cơ sở dữ liệu. Bây giờ hãy chuyển qua phần sức mạnh chính của SQL.
    Các lệnh trong SQL được bắt đầu với bất cứ từ khóa nào trong SQL như SELECT, INSERT, UPDATE, DELETE, ALTER, DROP, … và lệnh kết thúc với một dấu chấm phảy (winking. Ví dụ về một lệnh SQL:
    SELECT "ten_cot" FROM "ten_bang"; 
    Tại sao dấu chấm phẩy được sử dụng sau các lệnh trong SQL. Đó là bởi vì dấu này được sử dụng để phân biệt riêng rẽ giữa các lệnh trong SQL. Đây là chuẩn mực để phân biệt các lệnh SQL khi mà có nhiều hơn một lệnh cùng được sử dụng trong một lời gọi.
    Tôi xin phép chỉ viết những SQL đơn giản để mọi người tiện theo dõi.

    3.1.Truy vấn lựa chọn SELECT
    Mục đích: Lấy những thôn tin thỏa mãn điều kiện nào đó.
    Cú pháp:
    SELECT [tên trường 1], [tên trường 2] FROM [Tên bảng] WHERE [Tên trường 1] = 1 ORDER BY [Tên trường 1]
    Với lệnh này ta sẽ nhận được đối tượng RecordSet bao gồm 2 trường trong đó có tất cả các bản ghi thỏa mãn Tên trường 1 = 1 và được sắp xếp theo tên trường 1 theo thứ tự Nhỏ đến lớn (muốn từ lớn đến nhỏ ta thêm từ khóa DESC sau Tên trường 1 ở mục Order by.
    Ví dụ:
    Set rcs = dbs.OpenRecordSet (“Select * FROM [tblCaption] WHERE [fldName] = ‘Label’;”
    Ta sẽ thu được bảng rcs bao gồm các bản ghi có trường fldName có giá trị là Label. Lưu ý, khi kiểu trường là dạng ký tự ta cần có thêm các dấu nháy vào điều kiện.

    3.1.1.Mệnh đề DISTINCT trong SQL
    Mục đích: Lấy danh sách các đối tượng không trùng nhau trên 1 trường
    Cú pháp: SELECT DISTINCT cot1 FROM   ten_bang;

    3.1.2.Mệnh đề WHERE trong SQL
    Mục đích: Lấy danh sách các đối tượng thỏa mãn điều kiện
    Cú pháp: SELECT cot1, cot2....cotN FROM  ten_bang WHERE  DIEU_KIEN;

    3.1.3.Mệnh đề AND/OR trong SQL
    Mục đích: Xác lập điều kiện kiểm tra cho câu lệnh truy vấn
    Cú pháp:       SELECT cot1, cot2....cotN FROM  ten_bang
    WHERE  DIEU_KIEN_1 {AND|OR} DIEU_KIEN_2;

    3.1.4.Mệnh đề IN trong SQL
    Mục đích: Xác lập giá trị kiểm tra của điều kiện WHERE cho câu lệnh truy vấn
    Cú pháp:       SELECT cot1, cot2....cotN FROM   ten_bang
    WHERE  ten_cot IN (gtri-1, gtri-2,...gtri-N);
    ... Bài sẽ viết tiếp.
  • RE: Làm thế nào để dùng SQL trong lập trình?

    maidinhdan > 06-05-16, 03:04 PM

    Xin đóng góp 1 bài:


    Link: [Hàm] Demo Ứng dụng: Tự chuyển code SQL trong Query sang Code VBA để sử dụng


    Hình minh họa
    [Hình: sqltovba.png]

    Hy vọng nó hữu ích cho người mới bắt đầu.
  • RE: Làm thế nào để dùng SQL trong lập trình?

    hungle2006 > 07-05-16, 10:08 AM

    Bài viết rất hay, cảm ơn hai bác Paulsteigel và Maidinhdan, chúc hai bác khoẻ và đóng góp nhiều cho diễn đàn
  • RE: Làm thế nào để dùng SQL trong lập trình?

    Minh Tiên > 08-05-16, 11:14 AM

    Cảm ơn  paulsteigel ! Bài viết rất hay.
    Bạn cho mình hỏi: Ưu và khuyết điểm của 2 kiểu kết nối sớm và muộn ? Khi nào thì nên dùng kiểu kết nối nào ?
    Thanks !
  • RE: Làm thế nào để dùng SQL trong lập trình?

    paulsteigel > 08-05-16, 12:06 PM

    (08-05-16, 11:14 AM)Minh Tiên Đã viết: ....

    Theo đúng khái niệm thì Binding ở đây nên dịch là liên kết/ tham chiếu nhưng tôi dịch một cách nôm na để dễ tưởng tượng – đó là Kết nối.

    1. Vài nét về Kết nối Sớm và Muộn (Early binding and Late Binding)

    1.1. Kết nối muộn – Late bind
    Binding trong lập trình là công cụ để tự động hóa/ điều khiển các đối tượng ngoài (OLE). Ví dụ người ta hay kết nối Word/ Excel từ Access hoặc ngược lại ...vv để điều khiển các ứng dụng ngoài đó.
    Để thực hiện việc kết nối ngoài như vậy, các ứng dụng cần kết nối phải có các giao diện/ thư viện cho phép kết nối và phải được đăng ký với Hệ điều hành.
    Có 2 cách để thực hiện việc kết nối này đó là:
    Kết nối muộn (Late binding) bằng việc sử dụng từ khóa CreateObject để tạo ra phiên làm việc của ứng dụng cần kết nối theo đó bạn có thể điều khiển được nó. Ví dụ ta có thể tạo ra phiên làm việc mới của Excel bằng cách này với nhóm lệnh sau

    Mã:
    Dim oXL As Object
    Set oXL = CreateObject("Excel.Application")
    Ngoài ra, để điều khiển phiên làm việc của Excel đang chạy (Excel đã được khởi động), ta có thể dùng từ khóa GetObject (bất kể chúng ta đang dùng chế độ kết nối sớm hay muộn):

    Mã:
    Dim oXL As Object
    Set oXL = GetObject(, "Excel.Application")

    1.2. Kết nối sớm – Early bind
    Để sử dụng Kết nối sớm (early binding), đầu tiên, chúng ta cần khởi tạo tham chiếu (reference) thư viện ứng dụng cần kết nối và điều khiển với chương trình của bạn. Có thể làm việc này đơn giản bằng cách chọn Tools/ References trong màn hình soạn Code VBA của bất kỳ ứng dụng Office nào (chẳng hạn chọn “Microsoft Excel 12.0 Object Library”). Sau đó để khởi tạo phiên làm việc mới với Excel, bạn chỉ cần thực hiện đoạn lệnh sau:

    Mã:
    Dim oXL As Excel.Application
    Set oXL = New Excel.Application
    Lưu ý: Với cả 2 cách, điều đầu tiên nên kiểm tra xem có phiên làm việc hiện thời nào của Excel đang chạy không, nếu có thì hãy kết nối với nó trước để tận dụng luôn, nếu không có mới thực hiện tạo Kết nối mới. Điều này tránh việc tạo ra quá nhiều phiên làm việc trong quá trình chạy chương trình, gây ảnh hưởng hoặc lỗi hệ thống. Hãy xem đoạn mã sau đây dùng để tạo kết nối với Word nhé...

    Mã:
    Function CreateWordDocument(retApp As Object) As Object
       'Muc dich: Co gang thiet lap ket noi voi mot phien lam viec cua Word neu duoc. Neu khong thi tao moi
       Dim wrdApp As Object
       
       'Co gang tao ket noi
       On Error Resume Next
       Set wrdApp = GetObject(, "Word.Application")
       If Err.Number <> 0 Then
           'Khong tao duoc ketnoi
           Err.Clear
           Set wrdApp = CreateObject("Word.Application")
           wrdApp.Visible = True
       End If
       ' Doan code chinh...
       Set retApp = wrdApp
       Set CreateWordDocument = wrdApp.Documents.Add
    End Function

    2. Lợi ích của Kết nối sớm
    • Mã chương trình của bạn sẽ chạy nhanh hơn tương đối đấy. Đó là do mã chương trình đã được dịch sang mã máy ngay từ đầu trong khi đó, với Kết nối muộn, mã liên quan đến ứng dụng bạn cần kết nối sẽ chỉ được dịch khi nó chạy đến đoạn mã đó;
    • Do mã nguồn của bạn được dịch ngay từ đầu nên quá trình tìm lỗi, Debug sẽ dễ dàng hơn và trình dịch sẽ giúp bạn tìm lỗi chương trình mà bạn vô tỉnh quên xử lý trong quá trình thực hiện. Điều này không thể làm được khi bạn sử dụng Kết nối muộn;
    • Bạn có toàn quyền sử dụng tính năng tự động hoàn tất mã (Intellisense – trong quá trình viết code, chỉ cần gõ dấu chấm của đối tượng thì các thuộc tính và phương thức của đối tượng đó sẽ tự động hiển thị và chèn vào; bạn nhấn F1 thì cũng sẽ nhận được trợ giúp của chính ứng dụng đó ngay);
    • Ngoài ra, khi nhấn F2 trong màn hình soạn thảo Code, bạn cũng có thể đọc được toàn bộ các đối tượng, lớp, thuộc tính của ứng dụng cần kết nối;
    • Việc sử dụng các hàm/ thư viện/ hằng số của ứng dụng cũng tiện lợi, bạn không phải định nghĩa/ khai báo lại chúng như khi dùng Kết nối muộn. Nếu bạn muốn sử dụng Word từ Excel bạn chỉ cần làm thế này:

    Mã:
    Dim objWord As Word.Application
    Set objWord = New Word.Application
    With objWord
      .Visible = True
      .Activate
      .WindowState = wdWindowStateMaximize
      .Documents.Open ("c:\temp\temp.doc")
    End With
    Ngoài ra, khi bạn nhập .WindowState =, bạn sẽ thấy danh sách các hằng số hiện ra để chọn và chỉ cần chọn “wdWindowStateMaximize” từ danh sách. Trong khi đó, nếu dùng chế độ kết nối muộn, bạn sẽ phải tự nhập vào .WindowState = 1. ..  và bạn cũng cần phải biết xem giá trị của hằng số “wdWindowStateMaximize” là gì từ đó mới nhập vào giá trị là 1.
    Nói khác hơn, với Kết nối sớm, việc lập trình của bạn sẽ dễ hơn nhiều so với kết nối muộn.

    3. Lợi ích của Kết nối muộn
    Nhìn chung Kết nối muộn thường được người viết code có kinh nghiệm sử dụng do nó tránh được một số phiền toái:
    • Mã chương trình của bạn sẽ không phụ thuộc vào phiên bản ứng dụng bạn muốn điều khiển trong hệ thống. Ví dụ, bạn đã chọn tham chiếu đến “Microsoft Excel 12.0 Object Library”, khi thực hiện Kết nối sớm, ứng dụng của bạn sẽ chạy nếu trên hệ thống có Excel 12. Trong một số trường hợp do sự khác biệt về bộ thư viện do các phiên bản của Office, chương trình của bạn sẽ không chạy được. Với kết nối muộn, tôi chỉ cần khởi tạo Excel thì hệ thống sẽ tự tìm kiếm phiên bản Excel đang cài ổn định nhất để khởi động.
    • Kích thước chương trình của bạn sẽ nhỏ hơn nếu bạn tham chiếu đến nhiều ứng dụng và mất thêm thời gian để dịch;
    • Một số môi trường lập trình còn không cho bạn tạo liên kết đến ứng dụng khác.

    4. Kết luận
    Thường tôi sử dụng mềm dẻo giữa 2 kiểu kết nối.
    • Những gì ít thay đổi và phải dùng nhiều (DAO/ADODB) – tôi dùng Kết nối sớm;
    • Những gì thay đổi phiên bản nhiều trong khi tôi chỉ cần những thao tác tối thiểu (Excel/ Word...vv)– tôi dùng Kết nối muộn.
    Ví dụ mà tôi chia sẻ ở bài đầu là một cách nhìn.
  • RE: Làm thế nào để dùng SQL trong lập trình?

    paulsteigel > 08-05-16, 02:16 PM

    Sử dụng SQL thay cho việc tương tác trực tiếp với RecordSet
    Vấn đề này thực sự chả có gì to tát nhưng nó sẽ là cách để chúng ta thoát ly khỏi một vài phiền toái và nhàm chán khi phải thực hiện việc cập nhập bản ghi đối với các Form dạng Unbound!
    Ví dụ:
    Bạn muốn cập nhập 2 trường số liệu là Tuổi và Ngày thăm của Khách có tên Nguyễn Văn A đối với cửa hàng sách.
    Trong đó thông tin về chuyến thăm của khách được lưu vào bảng tblCustomerVisit với các trường như ID (Kiểu Autonumber), TenKhach (kiểu Text), Tuoi (Kiểu Number), NgayTham (Kiểu DateTime)
    Sẽ có 2 cách làm
    Cách 1: Dùng RecordSet
    Mã:
    Sub UpdateCustomer()
        ' Kiểm tra xem các dữ liệu có trống không
        If Nz(txtHovatenKhach, "") = "" Or Nz(txtNgayTham, 0) = 0 Or Nz(txtTuoiKhach, 0) = 0 Then GoTo ExitSub
        Dim rs As DAO.Recordset
        Set rs = CurrentDb.OpenRecordset("Select * from tblCustomerVisit Where TenKhach='" & txtHovatenKhach & "';")
        If rs.EOF Then GoTo ExitSub
        With rs
            .Edit
            .Fields("Tuoi") = txtTuoiKhach
            .Fields("NgayTham") = txtNgayTham
            .Update
        End With
    ExitSub:
        rs.Close
    End Sub

    Cách 2: Dùng SQL
    Mã:
    Private Sub UpdateCustomer_Click()
        'Kiểm tra xem các dữ liệu có trống không
        If Nz(txtHovatenKhach, "") = "" Or Nz(txtNgayTham, 0) = 0 Or Nz(txtTuoiKhach, 0) = 0 Then GoTo ExitSub
        Dim SqlTxt As String
        SqlTxt = "UPDATE tblCustomerVisit SET Tuoi= " & txtTuoiKhach & ", NgayTham=" & txtNgayTham & " " & _
            "WHERE TenKhach='" & txtHovatenKhach & "';"
        CurrentDb.Execute SqlTxt
    ExitSub:
    End Sub

    Cách 2 sẽ làm cho bạn đỡ phải lo lắng với việc thao tác với các đối tượng RecordSet và chỉ cần quan tâm tới SQL mà thôi.
    Với SQL ta có thể:
    Thêm bản ghi với SELECT ... INTO
    Xóa bản ghi với DELETE ... FROM
    và còn nhiều điều nữa - chúng ta sẽ cùng nghiên cứu tiếp
  • RE: Làm thế nào để dùng SQL trong lập trình?

    Che_Guevara > 08-05-16, 09:58 PM

    (08-05-16, 02:16 PM)paulsteigel Đã viết: Làm thế nào để dùng SQL trong lập trình?

    Anh Ngọc có rất nhiều bài viết hay.
    Xin cảm ơn a và các các thành viên trong diển đàn đã đóng góp trí tuệ, tâm huyết để cho các thành viên mới như e học hỏi.
  • RE: Làm thế nào để dùng SQL trong lập trình?

    paulsteigel > 09-05-16, 02:35 PM

    Bổ sung 1/ nhiều bản ghi vào bảng với SQL
    Với DAO/ADODB chúng ta sẽ phải sử dụng phương thức AddNew và sau đó là Update.
    Với SQL chúng ta cũng có thể làm như vậy với 2 cách sau đây:
    1. INSERT INTO [Tên bảng] ([Danh sách trường cách nhau bằng dấu phảy] VALUES ([Danh sách giá trị theo kiểu phù hợp*])
    Ghi chú: * [Danh sách giá trị theo kiểu phù hợp*] có nghĩa là:
    + Đối với trường Text, giá trị phải được đặt trong cặp dấu nháy đơn ''
    + Đối với trường ngày, giá trị phải được đặt trong cặp dấu ##

    2. SELECT [Danh sách trường] INTO [Tên bảng mới] [IN 'Đường dẫn đến cơ sở dữ liệu'] FROM [Tên bảng hiện tại]
    Lệnh này để lựa chọn danh sách trường để đẩy vào bảng mới (trong Cơ sở dữ liệu mới nếu có thêm từ khóa IN ..).
    Nếu dùng lệnh này mà không đặc tả điều kiện WHERE thì nó sẽ thêm hàng loạt bản ghi (trái với trường hợp 1 chỉ thêm 1 bản ghi).
  • RE: Làm thế nào để dùng SQL trong lập trình?

    Minh Tiên > 10-05-16, 09:30 AM

    Chào bạn Ngọc cùng các ACE Pro !
    Tiên có đoạn code Update dữ liệu bằng ADODB như sau:

    Mã:
    Function fUpdateDSHH()

       Dim strMahang As String, sqlUp As String, rs As Recordset, rsUp As ADODB.Recordset
       Set rs = CurrentDb.OpenRecordset("strTableNameTam")
       If rs.RecordCount > 0 Then
           rs.MoveFirst
           Do Until rs.EOF
           strMahang = rs!Mahang
           sqlUp = "Select * from tblDanhsach_Hanghoa Where Mahang='" & strMahang & "'"
           Call OpenConnect
           Set rsUp = New ADODB.Recordset
           rsUp.Open sqlUp, mConn, adOpenKeyset, adLockOptimistic
                   If rsUp.RecordCount > 0 Then
                       rsUp!Soluongton = rsUp!Soluongton + rs!Soluongnhap
                       rsUp!Dongianhap = rs!Dongianhap
                       rsUp!Dongiabanle = rs!Dongiabanle
                       rsUp!Dongiabansy = rs!Dongiabansy
                      ...
                       rsUp.Update
                   Else
                       rsUp.AddNew
                       rsUp!Mahang = rs!Mahang
                       rsUp!Tenhang = rs!Tenhang
                       rsUp!Donvitinh = rs!Donvitinh
                       rsUp!Nhomhang = rs!Nhomhang
                       rsUp!Nganhhang = rs!Nganhhang
                       rsUp!Soluongton = rs!Soluongnhap
                       rsUp!Dongianhap = rs!Dongianhap
                       rsUp!Dongiabanle = rs!Dongiabanle
                       ...
                       rsUp.Update
                   End If
           rs.MoveNext
           Loop
       End If
       rs.Close: rsUp.Close
       Call CloseConnect

    End Function

    Dùng để Update vào DSHH , chạy OK nhưng rất chậm. Bạn Ngọc cùng các Pro xem có cách nào cải tiến đoạn code để Update được nhanh hơn không ?
    Cảm ơn nhiều !