Đánh giá chủ đề:
  • 1 Votes - 5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Làm thế nào để dùng SQL trong lập trình?
#11
(10-05-16, 09:30 AM)Minh Tiên Đã viết: ....


Bài này xứng đáng là một bài hay về cách tư duy với SQL...
Do Tiên không gửi CSDL nên Ngọc làm tạm một bảng mô phỏng

Bản chất của sự việc là bạn muốn đưa thông tin từ bảng tạm này vào bảng tblDanhsach_Hanghoa
Vậy có 2 tình huống
1. Có thể có các bản ghi trong tblDanhsach_Hanghoa rồi
2. Chưa có - thì thêm vào

Vậy giải pháp như sau:
1. Liệt kê các bản ghi trong tblDanhsach_Hanghoa có mã hàng hóa trùng với Mahang trong strTableNameTam
Cập nhập tblDanhsach_Hanghoa với giá trị mới với query UPDATE

2. Liệt kê các bản trong strTableNameTam mà không có mã hàng hóa nào trùng với Mahang trong tblDanhsach_Hanghoa
Thêm vào với INSERT INTO.

Trong bài này có thêm khái niệm LEFT JOIN và INNER JOIN. Tôi sẽ giải thích sau.


Mã:
Sub UpdateHH()
    Dim SqlTxt As String
    ' Tat canh bao tu CSDL
    DoCmd.SetWarnings False
    
    ' Cap nhap nhung ma hang da co trong tblDanhsach_Hanghoa
    SqlTxt = "UPDATE tblDanhsach_Hanghoa AS d INNER JOIN ( " & _
        "SELECT b.Mahang, a.Dongianhap, a.Dongiabanle, a.Dongiabansy, [a].[Soluongton]+[b].[Soluongnhap] AS slTon " & _
        "FROM strTableNameTam AS b INNER JOIN tblDanhsach_Hanghoa AS a ON b.Mahang = a.Mahang) AS c " & _
        "ON d.Mahang = c.Mahang " & _
        "SET d.Soluongton = [c].[slTon], d.Dongianhap = [c].[Dongianhap], d.Dongiabanle = [c].[Dongiabanle], d.Dongiabansy = [c].[Dongiabansy];"
    ' O day co 2 Query, Query1_1 de lay danh sach nhung ban ghi co Mahang giong nhau giua tblDanhsach_Hanghoa strTableNameTam
    '   "SELECT b.Mahang, a.Dongianhap, a.Dongiabanle, a.Dongiabansy, [a].[Soluongton]+[b].[Soluongnhap] AS slTon " & _
    '   "FROM strTableNameTam AS b INNER JOIN tblDanhsach_Hanghoa AS a ON b.Mahang = a.Mahang
    ' Va Query 2 thuc hien viec UPDATE
    '   "UPDATE tblDanhsach_Hanghoa AS d INNER JOIN Query1_1 AS c " & _
    '    "ON d.Mahang = c.Mahang " & _
    '    "SET d.Soluongton = [c].[slTon], d.Dongianhap = [c].[Dongianhap], d.Dongiabanle = [c].[Dongiabanle], d.Dongiabansy = [c].[Dongiabansy];"
    
    ' Thuc thi lenh
    CurrentDb.Execute SqlTxt
    
    ' Them vao tblDanhsach_Hanghoa nhung cai khong co trong bang nay
    SqlTxt = "INSERT INTO tblDanhsach_Hanghoa ( Mahang, Tenhang, Donvitinh, Nhomhang, Nganhhang, Soluongton, Dongianhap, Dongiabanle, Dongiabansy ) " & _
        "SELECT a.Mahang, a.Tenhang, a.Donvitinh, a.Nhomhang, a.Nganhhang, a.Soluongnhap, a.Dongianhap, a.Dongiabanle, a.Dongiabansy " & _
        "FROM (SELECT c.Mahang, c.Tenhang, c.Donvitinh, c.Nhomhang, c.Nganhhang, c.Soluongnhap, c.Dongianhap, c.Dongiabanle, c.Dongiabansy " & _
        "FROM strTableNameTam AS c LEFT JOIN tblDanhsach_Hanghoa AS b ON c.Mahang = b.Mahang " & _
        "WHERE (((b.Mahang) Is Null))) AS a;"
    ' O day co 2 Query tuong tu nhu tren
    ' Querry1_2 xac dinh danh sach ban ghi trong strTableNameTam ma khong co trong tblDanhsach_Hanghoa
    '   "SELECT c.Mahang, c.Tenhang, c.Donvitinh, c.Nhomhang, c.Nganhhang, c.Soluongnhap, c.Dongianhap, c.Dongiabanle, c.Dongiabansy " & _
    '   "FROM strTableNameTam AS c LEFT JOIN tblDanhsach_Hanghoa AS b ON c.Mahang = b.Mahang " & _
    '   "WHERE (((b.Mahang) Is Null))
    
    ' Query thuc hien lenh chen ban ghi INSERT INTO (dat ten Query truoc la Querry1_2
    '   "INSERT INTO tblDanhsach_Hanghoa ( Mahang, Tenhang, Donvitinh, Nhomhang, Nganhhang, Soluongton, Dongianhap, Dongiabanle, Dongiabansy ) " & _
    '    "SELECT a.Mahang, a.Tenhang, a.Donvitinh, a.Nhomhang, a.Nganhhang, a.Soluongnhap, a.Dongianhap, a.Dongiabanle, a.Dongiabansy " & _
    '    "FROM Querry1_2 AS a;"
    CurrentDb.Execute SqlTxt
    DoCmd.SetWarnings True
End Sub
Chữ ký của paulsteigel ====================
Quốc gia hưng vong
Thất phu hữu trách
====================
Reply
Những người đã cảm ơn
#12
INNER JOIN - Kết hợp đồng dạng
Một trong những câu lệnh truy vấn thông dụng và quan trọng nhất trong việc liên kết 2 bảng đó là INNER JOIN..
Lệnh này giúp tạo ra bảng kết quả bằng cách kết hợp so sánh giá trị của 2 hoặc nhiều cặp cột của 2 bảng (ví dụ table1 và table 2) dựa trên chỉ dẫn cặp cột/ trường nào để so sánh giá trị. Truy vấn sẽ thực hiện so sánh mỗi dòng của bảng 1 với mỗi dòng của bảng 2 để tìm tất cả các cặp dòng của 2 bảng thỏa mãn chỉ dẫn so sánh. Khi thỏa mãn rồi, giá trị tìm được tương ứng của dòng A/B tìm thấy từ 2 bảng sẽ được trộn vào 1 bảng.
Nói một cách nôm na là: Tìm kết quả sao cho giá trị của 2 cột so sánh là bằng nhau.
Cú pháp

Mã:
SELECT table1.column1, table2.column2...
FROM table1
INNER JOIN table2
ON table1.common_field = table2.common_field;


Trong đó "ON table1.common_field = table2.common_field" là chỉ dẫn điều kiện so sánh

SQL JOIN (LEFT/RIGHT...)- Kết hợp khác dạng

INNER JOIN: Trả về tất cả các dòng phù hợp điều kiện cho trước từ 2 bảng
LEFT JOIN: Trả về tất cả các dòng từ bảng bên trái và các dòng thỏa mãn điều kiện từ bảng bên phải
RIGHT JOIN: Trả về tất cả các dòng từ bảng bên phải và các dòng thỏa mãn điều kiện ở bảng bên trái
Chữ ký của paulsteigel ====================
Quốc gia hưng vong
Thất phu hữu trách
====================
Reply
Những người đã cảm ơn Che_Guevara , Minh Tiên , maidinhdan
#13
Cảm ơn bạn Ngọc đã Hướng dẫn.
Tiên vẫn chưa thử được SQL theo cách của bạn. Tiên nói rõ hơn thế này:

1. tblDanhsach_Hanghoa được lưu trong 1 file da ta riêng mỗi lần thao tác thì kết nối qua ADODB.
2. strTableNameTam được xây dựng trong CurrentProject.

Khi thao tác xuất hàng hoặc nhập hàng thì làm trên strTableNameTam sau đó Update vào tblDanhsach_Hanghoa.

Thanks!
Chữ ký của Minh Tiên -----------------------------------------------
Đường tuy ngắn, không đi không đến
Việc tuy nhỏ, không làm không nên.
                                           Tuân Tử
-----------------------------------------------
Reply
Những người đã cảm ơn
#14
(10-05-16, 04:08 PM)Minh Tiên Đã viết: ....
Với trường hợp của Tiên thì cách làm thế này nhé...
1. Tạo ra một link từ CSDL hiện tại đến bảng tblDanhsach_Hanghoa trong CSDL tạm.
2. Thực hiện đoạn code tôi đã post

Vậy bổ sung đoạn code tạo link thế này nhé:
1. Kiểm tra xem link tblDanhsach_Hanghoa có tồn tại không?
2. Nếu có thì xem link này có tham chiếu đúng CSDL tạm không? Nếu không thì xóa đi.
3. Nếu không thì tạo ra
Kết thúc

Và dưới đây là phần code dành cho Tiên

Mã:
Option Compare Database
Option Explicit

Sub UpdateHH()
    Dim SqlTxt As String, dbPath As String
    ' Tat canh bao tu CSDL
    DoCmd.SetWarnings False
    '========================================
    ' TIEN SUA DUONG DAN FILE DB TAM NHE...
    '========================================
    dbPath = "E:\Users\Paulsteigel\Desktop\GPE\QbNHNhan\tmpDb.mdb"
    '========================================
    If Not CreateLink("tblDanhsach_Hanghoa", dbPath, "tblDanhsach_Hanghoa") Then Exit Sub
    
    ' Cap nhap nhung ma hang da co trong tblDanhsach_Hanghoa
    SqlTxt = "UPDATE tblDanhsach_Hanghoa AS d INNER JOIN ( " & _
        "SELECT b.Mahang, a.Dongianhap, a.Dongiabanle, a.Dongiabansy, [a].[Soluongton]+[b].[Soluongnhap] AS slTon " & _
        "FROM strTableNameTam AS b INNER JOIN tblDanhsach_Hanghoa AS a ON b.Mahang = a.Mahang) AS c " & _
        "ON d.Mahang = c.Mahang " & _
        "SET d.Soluongton = [c].[slTon], d.Dongianhap = [c].[Dongianhap], d.Dongiabanle = [c].[Dongiabanle], d.Dongiabansy = [c].[Dongiabansy];"
    ' O day co 2 Query, Query1_1 de lay danh sach nhung ban ghi co Mahang giong nhau giua tblDanhsach_Hanghoa strTableNameTam
    '   "SELECT b.Mahang, a.Dongianhap, a.Dongiabanle, a.Dongiabansy, [a].[Soluongton]+[b].[Soluongnhap] AS slTon " & _
    '   "FROM strTableNameTam AS b INNER JOIN tblDanhsach_Hanghoa AS a ON b.Mahang = a.Mahang
    ' Va Query 2 thuc hien viec UPDATE
    '   "UPDATE tblDanhsach_Hanghoa AS d INNER JOIN Query1_1 AS c " & _
    '    "ON d.Mahang = c.Mahang " & _
    '    "SET d.Soluongton = [c].[slTon], d.Dongianhap = [c].[Dongianhap], d.Dongiabanle = [c].[Dongiabanle], d.Dongiabansy = [c].[Dongiabansy];"
    
    ' Thuc thi lenh
    CurrentDb.Execute SqlTxt
    
    ' Them vao tblDanhsach_Hanghoa nhung cai khong co trong bang nay
    SqlTxt = "INSERT INTO tblDanhsach_Hanghoa ( Mahang, Tenhang, Donvitinh, Nhomhang, Nganhhang, Soluongton, Dongianhap, Dongiabanle, Dongiabansy ) " & _
        "SELECT a.Mahang, a.Tenhang, a.Donvitinh, a.Nhomhang, a.Nganhhang, a.Soluongnhap, a.Dongianhap, a.Dongiabanle, a.Dongiabansy " & _
        "FROM (SELECT c.Mahang, c.Tenhang, c.Donvitinh, c.Nhomhang, c.Nganhhang, c.Soluongnhap, c.Dongianhap, c.Dongiabanle, c.Dongiabansy " & _
        "FROM strTableNameTam AS c LEFT JOIN tblDanhsach_Hanghoa AS b ON c.Mahang = b.Mahang " & _
        "WHERE (((b.Mahang) Is Null))) AS a;"
    ' O day co 2 Query tuong tu nhu tren
    ' Querry1_2 xac dinh danh sach ban ghi trong strTableNameTam ma khong co trong tblDanhsach_Hanghoa
    '   "SELECT c.Mahang, c.Tenhang, c.Donvitinh, c.Nhomhang, c.Nganhhang, c.Soluongnhap, c.Dongianhap, c.Dongiabanle, c.Dongiabansy " & _
    '   "FROM strTableNameTam AS c LEFT JOIN tblDanhsach_Hanghoa AS b ON c.Mahang = b.Mahang " & _
    '   "WHERE (((b.Mahang) Is Null))
    
    ' Query thuc hien lenh chen ban ghi INSERT INTO (dat ten Query truoc la Querry1_2
    '   "INSERT INTO tblDanhsach_Hanghoa ( Mahang, Tenhang, Donvitinh, Nhomhang, Nganhhang, Soluongton, Dongianhap, Dongiabanle, Dongiabansy ) " & _
    '    "SELECT a.Mahang, a.Tenhang, a.Donvitinh, a.Nhomhang, a.Nganhhang, a.Soluongnhap, a.Dongianhap, a.Dongiabanle, a.Dongiabansy " & _
    '    "FROM Querry1_2 AS a;"
    CurrentDb.Execute SqlTxt
    DoCmd.SetWarnings True
End Sub

Function CreateLink(strTable As String, strPath As String, strBaseTable As String) As Boolean
    On Error GoTo CreateAttachedError
    Dim tdf As TableDef
    Dim strConnect As String
    Dim fRetval As Boolean
    Dim myDB As Database
    
    ' Kiem tra xem bang co ton tai khong?
    If TableExists(strTable) Then CurrentDb.TableDefs.Delete strTable
    
    Set myDB = CurrentDb
    Set tdf = myDB.CreateTableDef(strTable)
    
    With tdf
        .Connect = ";DATABASE=" & strPath
        .SourceTableName = strBaseTable
    End With
    
    myDB.TableDefs.Append tdf
    
    fRetval = True
    
CreateAttachedExit:
    CreateLink = fRetval
    Exit Function
    
CreateAttachedError:
    If Err = 3110 Then
        Resume CreateAttachedExit
    Else
        If Err = 3011 Then
            Resume Next
        End If
    End If
End Function

Function TableExists(tblName As String) As Boolean
    On Error GoTo ErrHandler
    Dim tdf As TableDef
    Set tdf = CurrentDb.TableDefs(tblName)
    Set tdf = Nothing
    TableExists = True
ErrHandler:
End Function
Chữ ký của paulsteigel ====================
Quốc gia hưng vong
Thất phu hữu trách
====================
Reply
Những người đã cảm ơn Minh Tiên , Che_Guevara
#15
Thanks Pau nhiều !
Tiên đã test Update bằng SQL theo hướng dẫn của bạn. Kết quả: Update rất nhanh.
Tiên đang kiểm tra lại thời gian Link table nữa. (Do mình chỉ mới Link thủ công để thử)
Ngọc cho mình hỏi: Trong hàm CreatLink của bạn. Trường hợp link table có Pass thì cần sửa lại code như thế nào ?
Cảm ơn nhiều !
Chữ ký của Minh Tiên -----------------------------------------------
Đường tuy ngắn, không đi không đến
Việc tuy nhỏ, không làm không nên.
                                           Tuân Tử
-----------------------------------------------
Reply
Những người đã cảm ơn paulsteigel
#16
Một chủ đề quá hay để học hỏi.
Chữ ký của Che_Guevara Hạnh phúc không phải là cảm giác tới đích mà là trên từng chặng đường đi!
Reply
Những người đã cảm ơn
#17
(11-05-16, 09:08 AM)Minh Tiên Đã viết: ....

Đây Tiên ơi,
Bản chất của liên kết trong Access là một shortcut có thông tin để access kết nối CSDL. Nó chả khác giề ông DAO hoặc ADODB connection string.
Giờ là lúc Tiên phải mày mò và tự đoán từ đoạn code sau của Ngọc nhé
Mã:
Function RemapLinks(Optional PwdString As String = "", Optional tPath As String = "") As DatabaseErrors
    ' Thực hiện việc tái lập liên kết bảng trong Access (với các Link đã có sẵn)
    Dim tdf As Object, tblName As String
    Err.Clear
    On Error GoTo ErrHandler
    For Each tdf In CurrentDb.TableDefs
        Debug.Print tdf.Name ' & " Type:" & tdf.Type
        If tdf.Connect <> "" Then
            tdf.Connect = "Ms Access;UID=Admin;PWD=" & PwdString & ";DATABASE=" & tPath
            tblName = tdf.Connect
            tdf.RefreshLink
        End If
    Next
    Set tdf = Nothing
    Exit Function
ErrHandler:
    RemapLinks = Err.Number
    If Err.Number <> 0 Then WriteLog Err.Description
End Function
Chữ ký của paulsteigel ====================
Quốc gia hưng vong
Thất phu hữu trách
====================
Reply
Những người đã cảm ơn Minh Tiên
#18
Thanks Pau nhiều !
Mình đã làm OK ! Nhanh hơn code cũ chuối của mình nhiều.
Việc thực thi SQL rất OK.
Tuy nhiên Tiên vẫn đang phân vân chưa lý giải được:

1. Nếu chạy qua Lan mà Link table ở tất cả các PC qua 1 data thì có vấn đề gì ko ?
2. Nếu như thế thì có cần thiết phải viết bằng ADODB để chạy Lan cho nhiều PC ko ?

Nhờ Pau và các Pro chỉ giúp !
Chữ ký của Minh Tiên -----------------------------------------------
Đường tuy ngắn, không đi không đến
Việc tuy nhỏ, không làm không nên.
                                           Tuân Tử
-----------------------------------------------
Reply
Những người đã cảm ơn
#19
(11-05-16, 03:17 PM)Minh Tiên Đã viết: ....

Tiên cần mô hình hóa lên thì mình mới đáp lời được!
Phần chạy trên các máy thì để ở các máy hay ở đâu?
Data để ở máy chủ hay ở đâu
File tạm để ở đâu?....
Cái đó chắc Tiên biết rõ. Khi có đủ thông tin mình sẽ thưa thớt!
Chữ ký của paulsteigel ====================
Quốc gia hưng vong
Thất phu hữu trách
====================
Reply
Những người đã cảm ơn Che_Guevara
#20
Thanks Pau !
1. Da ta mình để trên 1 PC riêng (Chỉ phần table).
2. Các PC (Dự kiến khoản 5 PC) khác mình dùng để chạy chương trình Bán hàng được Thiết kế gồm các đầy đủ các thành phần những table chỉ là các table tạm dùng để thao tác.
Khi xuất hàng bán thì ghi các nội dung xuất trong table tạm, khi lưu --> Ghi và table ở da ta.
3. À mình có đoạn code dùng SQL để Insert vào table (chỉ thêm mới):

Mã:
...
SqlTxt = "INSERT INTO tblNhaphang_Muavao_Chitiet (Stt,Mahang,Tenhang,Donvitinh,Nhomhang,Nganhhang,Soluongnhap,"
   SqlTxt = SqlTxt & "Dongianhap,Dongiabanle,Dongiabansy,Thanhtiennhap,Tienchietkhau,Hansudung,Ngaykiemke)"
   SqlTxt = SqlTxt & " SELECT Stt, Mahang,Tenhang,Donvitinh,Nhomhang,Nganhhang,Soluongnhap,Dongianhap,"
   SqlTxt = SqlTxt & "Dongiabanle,Dongiabansy,Thanhtiennhap,Tienchietkhau,Hansudung,Ngaykiemke FROM tblNhaphang_Muavao_Chitiet_Tam;"
   CurrentDb.Execute SqlTxt
Không biết lỗi chỗ nào mà Insert ko được
4. Mình muốn Insert thêm 1 Field vào tblNhaphang_Muavao_Chitiet mà không lấy từ tblNhaphang_Muavao_Chitiet_Tam mà lấy từ Form thì làm cách nào ?

Rất mong Pau cùng các ACE Pro chỉ giúp !
Cảm ơn nhiều !
Chữ ký của Minh Tiên -----------------------------------------------
Đường tuy ngắn, không đi không đến
Việc tuy nhỏ, không làm không nên.
                                           Tuân Tử
-----------------------------------------------
Reply
Những người đã cảm ơn


Có thể liên quan đến chủ đề
Chủ đề: Tác giả Trả lời: Xem: Bài mới nhất
  [Help] Xin giúp đỡ về sử dụng hàm Dlookup với nhiều điều kiện dangh5 1 74 30-11-16, 10:44 PM
Bài mới nhất: dangh5
  [Hỏi] Sự khác nhau của Like và "=" trong các hàm D toancvp 6 203 10-11-16, 12:01 AM
Bài mới nhất: toancvp
  Thay thế giá trị từ cột này sang cột khác trong 1 query trungminh 6 139 08-11-16, 03:24 PM
Bài mới nhất: ongke0711
  [Help] Gộp nhiều dòng có cùng điều kiện lên chung một dòng trong query tronghieu9792 4 181 03-11-16, 09:58 AM
Bài mới nhất: tronghieu9792
  [Hỏi] Cách lọc trong query trungdv007 10 355 11-10-16, 08:30 AM
Bài mới nhất: trungdv007

Chuyển nhanh:


User(s) browsing this thread: 1 Guest(s)
Diễn Đàn Thơ Văn Thi Ẩm Lâu|Nhà Hàng Sông Thơ