Nhờ các anh, chị chỉ giúp có cách nào đưa dữ liệu từ excel vào sql server bằng VBA nhanh nhất đối với nguồn dữ liệu trên 10k dòng mà không bị treo file excel không ah, Em áp dụng câu lệnh insert into nó chậm và treo máy khi dữ liệu lớn.
Vậy bạn thử for.. next dữ liệu rồi đưa hết vào câu lệnh insert into cuối cùng là ghi vào xem vấn đề gì không (nghĩa là ghi 1 lần) thay vì mỗi vòng lặp là 1 lần ghi vào.Nhờ các anh, chị chỉ giúp có cách nào đưa dữ liệu từ excel vào sql server bằng VBA nhanh nhất đối với nguồn dữ liệu trên 10k dòng nhanh nhất mà không bị treo file excel không ah, Em áp dụng câu lệnh insert into nó chậm và treo máy khi dữ liệu lớn.
Mình đã thử rất nhiều cách,trong đó có cách của bạn nhưng cũng không nhanh hơn dc vì nó phải chạy lệnh insert thì sẽ không nhanh được.Vậy bạn thử for.. next dữ liệu rồi đưa hết vào câu lệnh insert into cuối cùng là ghi vào xem vấn đề gì không (nghĩa là ghi 1 lần) thay vì mỗi vòng lặp là 1 lần ghi vào.
Cách nào chẳng phải for next bạn, cách của mình là câu lệnh insert sẽ nằm ngoài vòng lặp sau khi kết thúc mà bạn.. cách bạn có giống không?Mình đã thử rất nhiều cách,trong đó có cách của bạn nhưng cũng không nhanh hơn dc vì nó phải chạy lệnh insert thì sẽ không nhanh được.
Rồi insert vào kiểu gì bạn thử demo cho mình dc không?Cách nào chẳng phải for next bạn, cách của mình là câu lệnh insert sẽ nằm ngoài vòng lặp sau khi kết thúc mà bạn.. cách bạn có giống không?
Vậy code của bạn đâu?Rồi insert vào kiểu gì bạn thử demo cho mình dc không?
Cách của ban có lẽ là tạo 1 chuỗi dữ liệu theo cấu trúc bảng rồi thực thi câu lệnh insert,cách này mình đã làm dữ liệu lớn nó chạy miệt mài bạn oi.Rồi insert vào kiểu gì bạn thử demo cho mình dc không?
Mình tạo sẵn bảng trên sql và nguoi dùng họ nhấn nút để đẩy dữ liệu lên đó thì có gì sai bạn.Bên SQL Server, lập cái SP nó import từ Excel. Chứ ai lại đi ngược vậy.
SQL Server, dùng SP thì khá an toàn. Đi từ VBA qua thì câu kết nối phải cởi cái lớp an toàn của SQL Server. Đang không tự giao chìa khoá nhà cho người ngoài.
Từ Excel vào nơi khác thì gọi là Export chứ đâu phải Import.
C1: Bạn đã thử dùng ADODB Recordset chưa?Nhờ các anh, chị chỉ giúp có cách nào đưa dữ liệu từ excel vào sql server bằng VBA nhanh nhất đối với nguồn dữ liệu trên 10k dòng mà không bị treo file excel không ah, Em áp dụng câu lệnh insert into nó chậm và treo máy khi dữ liệu lớn.
Cách của ban có lẽ là tạo 1 chuỗi dữ liệu theo cấu trúc bảng rồi thực thi câu lệnh insert,cách này mình đã làm dữ liệu lớn nó chạy miệt mài bạn oi.
Bài đã được tự động gộp:
Mình tạo sẵn bảng trên sql và nguoi dùng họ nhấn nút để đẩy dữ liệu lên đó thì có gì sai bạn.
Kiểu này nè bạn:Rồi insert vào kiểu gì bạn thử demo cho mình dc không?
data = rng.Resize(lastRow, lastCol).Value
For j = 1 To lastCol
If j = 1 Then
sColName = data(1, j)
Else
sColName = sColName & "," & data(1, j)
End If
Next j
For i = 2 To lastRow
For j = 1 To lastCol
If i = 2 Then
str = data(i, j)
Else
str = "'" & data(i, j) & "'"
End If
If j = 1 And i = 2 Then
aInsert = "(" & str
ElseIf j = 1 Then
aInsert = aInsert & ",(" & str
Else
aInsert = aInsert & "," & str
End If
Next j
aInsert = aInsert & ")"
Next i
strSQL = "INSERT INTO " & "[" & sDBName & "].[dbo].[" & sTbName & "] (" & sColName & ") VALUES " & aInsert
cnn.Execute (strSQL)
SQL Server phải cho phép VBA kết nối....
Mình tạo sẵn bảng trên sql và nguoi dùng họ nhấn nút để đẩy dữ liệu lên đó thì có gì sai bạn.
Ok nhưng dữ liệu lớn chạy chậm lắm bạn. Ban có cách nào nhanh hơn chỉ mình với.Kiểu này nè bạn:
Mã:data = rng.Resize(lastRow, lastCol).Value For j = 1 To lastCol If j = 1 Then sColName = data(1, j) Else sColName = sColName & "," & data(1, j) End If Next j For i = 2 To lastRow For j = 1 To lastCol If i = 2 Then str = data(i, j) Else str = "'" & data(i, j) & "'" End If If j = 1 And i = 2 Then aInsert = "(" & str ElseIf j = 1 Then aInsert = aInsert & ",(" & str Else aInsert = aInsert & "," & str End If Next j aInsert = aInsert & ")" Next i strSQL = "INSERT INTO " & "[" & sDBName & "].[dbo].[" & sTbName & "] (" & sColName & ") VALUES " & aInsert cnn.Execute (strSQL)
Mình thấy bài 9 của anh @ongke0711 có gợi ý 2 cách đó mà chưa thấy bạn phản hồi.Ok nhưng dữ liệu lớn chạy chậm lắm bạn. Ban có cách nào nhanh hơn chỉ mình với.
Nhìn hấp dẫn quá,chia sẻ cho em học để áp dụng với anhĐang rảnh làm cái test transfer data các kiểu xem như thế nào nhé.
- Dữ liệu: 30k dòng x 15 cột
- Mới test 2 cách đã đề cập: dùng SP để bulk insert cực kỳ nhanh nhưng đổi lại là user phải có quyền Admin mới xài được lệnh này.
View attachment 275069
C1 mình đã làm nhưng vần không nhanh hơn được.C1: Bạn đã thử dùng ADODB Recordset chưa?
- Kết nối SQL Server, mở ADO Recordset từ Table đích.
- Đưa dữ liệu Excel vào Array rồi AddNew vào ADO Recordset -> UpdateBatch.
Cách này chắc chắn nhanh hơn Insert into.
C2: Chuyển dữ liệu Excel thành CSV rồi Bulk Insert vào SQL SV. Cái này viết SP.
'Sub NL_TH_KHTT()Code bạn làm như thế nào? Xem thử nguyên nhân nó ra sao.
Theo tôi thấy code bạn làm sai ý rồi, cố gắng mò đi cho nhớ'Sub NL_TH_KHTT()
' 'FORM_LOG.Show
' Call connect_data.connect_sql
' Dim rs, rs1 As Object
' Dim delete_query, select_query As String
' delete_query = "truncate table [CSDL_LDA].[KHOAN_PHONG].[NL_TH_KHTT]"
' Set rs = cn.Execute(delete_query)
' select_query = "Select * from [CSDL_LDA].[KHOAN_PHONG].[NL_TH_KHTT] "
' Set rs1 = CreateObject("adodb.RecordSet")
' rs1.Open select_query, cn, 1, 3
' Dim xlRow, last_row As Long
' Dim xlCol As Integer
' last_row = ThisWorkbook.Worksheets("NL_TH_KHTT").Cells(Rows.Count, 1).End(xlUp).Row
' For xlRow = 2 To last_row
' rs1.AddNew
' For xlCol = 1 To 20
' rs1.Fields(Cells(1, xlCol).Value) = Cells(xlRow, xlCol).Value
' Next xlCol
'Next xlRow
'rs1.updateBatch
' cn.Close
' Set cn = Nothing
' Set rs1 = Nothing
' Set rs = Nothing
' End Sub
Bạn xem thử vì sao nó chậm lắm luôn á, còn chậm hơn cả cách insert into ngoài vòng for .. next
' Dim rs, rs1 As Object
' For xlCol = 1 To 20
' rs1.Fields(Cells(1, xlCol).Value) = Cells(xlRow, xlCol).Value
' Next xlCol
'Next xlRow
Bạn xem thử vì sao nó chậm lắm luôn á, còn chậm hơn cả cách insert into ngoài vòng for .. next
Hic nó chi chạy chậm chứ nó không hề báo lỗi gì.Bạn có thể chia sẽ cho mình cách bulk insert vba được không?- Dính lỗi khai báo biến gộp. Có bài nói rồi.
- Mỗi lần lấy dữ liệu là mỗi lần tương tác với Sheet.
- Các Action query (Delete, Insert, update) thì chỉ cần thực thi, không cần phải qua đối tượng Recordset. Dùng thẳng đối tượng ADO Connection hoặc ADO Command.
- Code VBA còn lủng củng thì sẽ khó hơn khi tương tác với stored procedure của SQL Server.
Nên hỏi IT phụ trách cơ sở dữ liệu đó.Nhờ các anh, chị chỉ giúp có cách nào đưa dữ liệu từ excel vào sql server bằng VBA nhanh nhất đối với nguồn dữ liệu trên 10k dòng mà không bị treo file excel không ah, Em áp dụng câu lệnh insert into nó chậm và treo máy khi dữ liệu lớn.
C1 mình đã làm nhưng vần không nhanh hơn được.
C2 thì mình không biết, bạn có thể hướng dẫn mình được không ?
mConnectionString = "Network Library=DBMSSOCN;" & _
"PROVIDER=MSOLEDBSQL;DATA SOURCE=" & mServerName & _
";INITIAL CATALOG=" & mDatabaseName & _
";User Id=" & mUserName & ";Password=" & mPassword & ";"
mConnectionString = "Driver={SQL Server};" & _
"Server=" & mServerName & _
";Database=" & mDatabaseName & _
";Uid=" & mUserName & _
";Pwd=" & mPassword & ";"
'";DataTypeCompatibility=80;" 'dung cho SQL SV 2019 với các datatype moi'
Cảm ơn Ongke0711 đã chia sẻ.Bạn xem file đính kèm.
- Mở SQL Server và chạy lần lượt 3 cái SQL script để tạo: TestDB, tblRawData và cái stored procedure Bulk insert.
- Chạy file Excel và nhập các thông số kết nối tới máy chủ SQL Server của bạn.
Private Const adUseClient As Long = 3
Private Const adLockReadOnly As Long = 1
Private Const adStateOpen As Long = 1
Private Const adCmdStoredProc As Long = 4
Private Const adParamOutput As Long = 2
Private Const adOpenDynamic As Long = 2
Private Const adOpenStatic As Long = 3
Public Enum DBaseType
dbSQLServer = 1
dbAccess = 2
dbIBMDADB2 = 3
End Enum
rs1.Open select_query, cn , adOpenKeySet, adLockOptimistic
rs1.Open select_query, cn, 1, 3
lần thứ n cảm ơn Bác.Code gốc của tôi dùng khai báo muộn (Late binding) với thư viện ADODB, nên nếu dùng tên hằng như:
rs1.Open select_query, cn , adOpenKeySet, adLockOptimistic
sẽ báo lỗi ngay vì VBA nó không hiểu các tham số đó là gì nếu chưa khai báo nó.
Nếu truyền tham số trong câu lệnh bằng các con số thì sẽ không báo lỗi nhưng không phải ai cũng nhớ nó là tham số gì. Người ta hay gọi là Magic number.
Mã:rs1.Open select_query, cn, 1, 3
Do đó tôi khai báo các hằng trên để có thể dùng cái tên nó luôn trong câu lệnh đối với Late binding.
Còn phần khai báo: DBType là vì tôi dùng bộ code này để kết nối với 2 loại CSDL khác là Access và IBMDB. Khi kết nối với CSDL nào thì cung cấp tham số này để code nó tạo chuỗi kết nối phù hợp với loại CSDL đó.
Tài liệu tham khảo: đính kèm bên dưới.
cảm ơn bạn rất nhiều.Bạn xem file đính kèm.
- Mở SQL Server và chạy lần lượt 3 cái SQL script để tạo: TestDB, tblRawData và cái stored procedure Bulk insert.
- Chạy file Excel và nhập các thông số kết nối tới máy chủ SQL Server của bạn.
Bổ sung: Tùy phiên bản và thiết lập SQL Server của bạn mà thay đổi Connection String cho phù hợp nhé.
Mã:mConnectionString = "Network Library=DBMSSOCN;" & _ "PROVIDER=MSOLEDBSQL;DATA SOURCE=" & mServerName & _ ";INITIAL CATALOG=" & mDatabaseName & _ ";User Id=" & mUserName & ";Password=" & mPassword & ";"
Mã:mConnectionString = "Driver={SQL Server};" & _ "Server=" & mServerName & _ ";Database=" & mDatabaseName & _ ";Uid=" & mUserName & _ ";Pwd=" & mPassword & ";" '";DataTypeCompatibility=80;" 'dung cho SQL SV 2019 với các datatype moi'
khai báo mấy biến chung này