Datetime format trong SQL-VBA

  • Thread starter hai_kt
  • Ngày gửi
H

hai_kt

Guest
29/5/06
4
0
1
Bình Định
Xin chào!!!!!

File nhogiup.rar của anh Đào Việt Cường (các bạn xem bài viết liên quan ở đây) đáp ứng được vấn đề cập nhật dữ liệu nhưng không nghiệm đúng điều kiện lọc.
Các cao thủ access có thể xem lại vấn đề này không, tôi cũng muốn tham khảo thêm vấn đề này!
Chào trân trọng!!!!!!

hai_kt!
dance2: :pepsi:
 
Sửa lần cuối bởi điều hành viên:
Khóa học Quản trị dòng tiền
Đào Việt Cường

Đào Việt Cường

Moderator
22/11/05
400
4
18
Khánh Hòa
Dear hai_kt,------------Bạn có thể nói rõ hơn "vấn đề không nghiệm đúng điều kiện lọc" được không? Mình đã xem lại nhưng mà không thấy trường hợp dữ liệu không cập nhật đúng theo điều kiện lọc cả, trừ trường hợp bạn truyền hai tham số không đúng. Điều này bắt buộc phải "Validate" cho 2 text box một cách toàn vẹn hơn thôi!Các bạn nên mô tả càng cụ thể vấn đề thì các giải đáp sẽ chính xác và đầy đủ!
 
L

lehongduc

Trung cấp
29/3/05
131
1
18
64
VietNam
Định dạng ngày trong câu lệnh SQL

VAS nói:
Mình có một cách làm "NÔNG DÂN" như sau

1/ Khai báo 2 biến Bắt đầu và cho đến

Public NgayBatdau as date
Public NgayChoden as date
2/ Hai hàm để lấy giá trị bắt đầu và cho đến

Public Function F_batdau()
F_Batdau = NgayBatdau
End Function

Public Function F_Choden()
F_Choden = NgayChoden
End Function

3/ Public Sub TINHPS(BatDau As Date, ChoDen As Date)

a/Gan gia tri cho Ngaybatdau , va NgayChoden

Ngaybatdau = BatDau
NgayChoDen = Choden

b/WHERE (******) between BatDau and ChoDen
Ban thay dòng lenh này bằng

WHERE (*******) between F_Batdau() and F_Choden()

và dùng lệnh docmd.runsql là xong.


Hy vọng bạn thành công

Cheers

VAS

PP: bạn nên kết hợp hàm Format với ngày sẽ chính xác hơn

Xin chào các Bác,
Với câu lệnh SQL bắt buộc phải tuân thủ quy định sau: tất cả các định dạng ngày đều phải theo đúng định dạng "mm/dd/yyyy"
Vì vậy, cách tốt nhất khi có 1 phép toán với dữ liệu kiểu Date trong câu lệnh SQL ta nên chuyển nó sang đúng định dạng nêu trên. Dưới đây là một cách làm luôn đúng mà không phụ thuộc vào việc hệ thống đang được set theo định dạng ngày như thế nào:
"BETWEEN " & "#" & format$(TuNgay,"mm/dd/yyyy") & "#" & " AND " & "#" & format$(DenNgay,"mm/dd/yyyy") & "#"
Với câu lệnh SQL trên, đoạn sau đây chính là dữ liệu đã được định dạng:
"#" & format$(TuNgay,"mm/dd/yyyy") & "#"
 
Đào Việt Cường

Đào Việt Cường

Moderator
22/11/05
400
4
18
Khánh Hòa
lehongduc nói:
Với câu lệnh SQL bắt buộc phải tuân thủ quy định sau: tất cả các định dạng ngày đều phải theo đúng định dạng "mm/dd/yyyy"
Vì vậy, cách tốt nhất khi có 1 phép toán với dữ liệu kiểu Date trong câu lệnh SQL ta nên chuyển nó sang đúng định dạng nêu trên ("#" & format$(TuNgay,"mm/dd/yyyy") & "#"). Với câu lệnh SQL trên, đoạn sau đây chính là dữ liệu đã được định dạng:
"#" & format$(TuNgay,"mm/dd/yyyy") & "#"
Dear lehongduc,
---------------
Liệu có phải "bắt buộc phải tuân thủ" không bác?
Theo em hiểu thì các định dạng (format) và kiểu (type) không làm thay đổi giá trị (Value). Chúng ta đang truy vấn tới một giá trị thì cho dù có format ở định dạng nào, giá trị đó cũng không hề thay đổi. Kiểu dữ liệu Datetime thực chất là Numberic, nó không phụ thuộc vào định dạng dd/mm/yyyy.
Để truy vấn đến giá trị này thay vì sử dụng cập dấu nháy kép "" như biểu diễn trích xuất một chuỗi "String" thì ta sử dụng cặp dấu ## để biểu diễn giá trị kiểu thời gian #Datetime#. Hai cách biểu diễn này là để phân biệt String và Datetime. Ví dụ:
#31/5/2006# là một Datetime (chúng ta có thể #31/5/2006# +1 = #1/6/2006#), và:
"31/5/2006" là một String, chúng ta không thể "31/5/2006" +1 (is ERROR!).
Vì vấn đề này liên quan đến kiến thức cơ bản về MSA, nên em muốn mình không bị hiểu sai cơ bản, mong bác chỉ bảo thêm!:friend:
 
Sửa lần cuối:
H

hai_kt

Guest
29/5/06
4
0
1
Bình Định

Xin chào!!!!!!
Các bác, các chú tranh luận xôi nổi quá. hai_kt cũng đó tìm hiểu khá nhiều nhưng vẫn chưa nghĩ ra.
Tôi nghĩ vấn đề xuất phát từ đoạn WHERE trở về sau,việc cập nhật dữ liệu trong nhogiup.rar không tuân thủ thủ theo lệnh của "anh" này. Để có thể thấy rõ hơn, hãy bỏ đi đoạn này WHERE (T_PHIEUTH.ngay) between #" & dtTuNgay & "# and #" & dtDenNgay & "#
Việc cập nhật dữ liệu vẫn không thay đổi gì so với trước.
Thật tình không hiểu nổi , "bó tay". Các chuyên gia xem lại thử đi.
:drummer:
 
Đào Việt Cường

Đào Việt Cường

Moderator
22/11/05
400
4
18
Khánh Hòa
hai_kt nói:
Để có thể thấy rõ hơn, hãy bỏ đi đoạn này WHERE (T_PHIEUTH.ngay) between #" & dtTuNgay & "# and #" & dtDenNgay & "#
Việc cập nhật dữ liệu vẫn không thay đổi gì so với trước.
Dear hai_kt,
Mình hiểu vấn đề của bạn rồi, có thể bạn chưa định dạng ngày hệ thống theo dạng tiêu chuẩn dd/MM/yyyy trên máy tính của bạn nên có thể bạn đã nhầm. Ví dụ bạn muốn xoá những giao dịch trong ngày mùng 3 tháng 1 năm 2005 nhưng do ngày hệ thống trên máy tính của bạn đang được định dạng là MM/dd/yyyy, đã nhập vào text box Từ ngày= 03/01/2005 , Đến ngày = 03/01/2005.(?) Nhưng thực chất đó là ngày mùng 1 tháng 3 năm 2005. Điều này có thể đã làm bạn hiểu sai do truy vấn không theo đúng ý bạn mong muốn.
Và bạn cũng đừng hiểu nhầm cho cái anh "WHERE" mà anh ta tủi thân. Trong ngôn ngữ SQL, từ khoá WHERE được sử dụng như "criteria" nhằm cung cấp cho ta điều kiện lọc. Sau WHERE bao giờ cũng là một biểu thức luận lý (logic). Kết quả truy vấn phụ thuộc vào điều kiện này, nếu bỏ đi WHERE có nghĩa là bạn SELECT toàn bộ các mẩu tin mà không quan tâm đến điều kiện gì. Kết quả của hai truy vấn (có WHERE hay không có WHERE) chỉ giống nhau khi tất cả các mẩu tin đều thoả mãn điều kiện.
Bạn kiểm tra lại một lần nữa xem sao, mình thử đi thử lại mà không phát hiện ra lỗi như bạn mô tả!:worry: :hacker:
 
HongViet

HongViet

Cao cấp
10/11/05
286
10
18
Đà nẵng
Tôi nghỉ vấn đề ở đây là hai cái biến đấy!

Này nha: Bạn thử dùng Inputbox để gán vô 2 biến ngày trước đó xem sao & dùng Sendkeys, OK ngay tấp lự!; Tất nhiên làm để rõ vấn đề thôi; chứ nên lấy ở chổ khác như ở Controls, . . . Hình như nhớ không lầm biến này phải là Variant thì phải!:dance2:
 
Đào Việt Cường

Đào Việt Cường

Moderator
22/11/05
400
4
18
Khánh Hòa
Sao vấn đề này lại trở nên phức tạp thế nhỉ?

Dear HongViet,
--------------
Cứ cho là vấn đề là do hai biến đi, nhưng vì sao lại phải dùng InputBox và SendKeys hả anh? Theo em để kiểm tra chính xác lỗi này, sau mệnh đề WHERE chúng ta đưa trực tiếp các giá trị ngày tháng vào? Sau đây là thủ tục kiểm tra giá trị của hai biến dtTuNgay và dtDenNgay được gán trực tiếp:
Public Sub ImportTransaction(dtTuNgay As Date, dtDenNgay As Date)
dtTuNgay = #1/3/2005#
dtDenNgay = #1/4/2005#
Debug.Print "From: " & dtTuNgay & " (val = " & CDbl(dtTuNgay) & ") to: " & dtDenNgay & " val = (" & CDbl(dtDenNgay) & ")"
End Sub
Thủ tục này sẽ cho chúng ta thấy giá trị thực sự của biến khi ta chuyền vào. Và để biết chắc chắn biến được truyền từ text box có đúng như ta mong muốn thì có thể kiểm tra:

Private Sub cmbImportTransaction_Click()
ImportTransaction txbTungay.Value, txbDenngay.Value
End Sub
_____________________________________________

Public Sub ImportTransaction(dtTuNgay As Date, dtDenNgay As Date)
Debug.Print "From: " & dtTuNgay & " (val = " & CDbl(dtTuNgay) & ") to: " & dtDenNgay & " val = (" & CDbl(dtDenNgay) & ")"
End Sub
Đến đây thì chúng ta hiểu rằng sẽ phải truyền tham số như thế nào cho đúng!
 
Sửa lần cuối:
paulsteigel

paulsteigel

Trung cấp
13/11/05
103
0
16
48
Hoà Bình
www.sfdp.net
Chào các bạn,
Dạo qua một số chủ đề mình thấy các bạn bàn luận sôi nổi quá, rất nhiều chủ đề thật hay và cũng rất thú vị.
Những ngày qua, chắc cũng có rất nhiều người giống mình, tất cả đều rất buồn.
Quay lại chủ đề về vấn đề ngày tháng trong CSDL, tôi xin mạn phép bàn mấy điều như sau:
  • Cơ cấu lưu trữ dữ liệu kiểu ngày tháng.
  • Nguyên tắc xử lý dữ liệu kiểu ngày tháng trước khi đưa và CSDL của Access.
  • Một số thủ thuật xử lý.
Trong máy tính nguyên tắc lưu trữ dữ liệu kiểu thời gian (Datetime) dựa trên nhu cầu xử lý dữ liệu tối thiểu của người dùng (tức là xem xét mức quản lý thời gian đến của anh ta). Đơn vị tối thiểu để thông dụng nhất là giây và đơn vị tối đa thông dụng nhất là năm, vì thế người ta dùng cách thức mà tôi hình tượng hoá theo dạng sau đây để lưu trữ kiểu dữ liệu ngày tháng. Mm/dd/yyyy HH:MM:SS
Trong đó mm là tháng (từ 1 đến 2 chữ số), dd là ngày (từ 1 đến 2 chữ số) và yyyy là năm có 4 chữ số. HH là giờ, mm là phút và ss là giây.
Bất kể bạn định dạng ngày giờ theo vùng quốc gia thế nào dd/mm/yyyy hay yyyy/mm/dd … thì máy tính luôn chọn chuẩn nói trên để lưu trữ ngày tháng.
Vậy vấn đề nảy sinh là tập quán người dùng trong lưu trữ ngày tháng cũng có thể gây ra một số điều không như ý khi lưu trữ đơn vị dữ liệu kiểu thời gian. Nếu bạn dùng định dạng thời gian hệ thống là dd/mm/yyyy (kiểu Locale Setting của các nước theo chuẩn của Pháp) thì sẽ có nhiều vấn đề khi chuyển đổi dữ liệu nhập vào sang kiểu ngày tháng.
Do đặc tính VB có khả năng tự chuyển đổi định dạng dữ liệu khi có một số đặc tả nhất định để tiến hành các phép toán nên chúng ta cần đặc biệt lưu ý.
Xét ví dụ #15/10/2005#, trong bất kỳ tình huống sử dụng nào, thì VB sẽ luôn cho ta kết quả là tháng 10, ngày 15.
Nhưng xét ví dụ #1/10/2005# thì VB sẽ luôn hiểu đây là ngày 10 tháng 1.
Vậy tức là khi tiến hành chuyển đổi, VB xét chuỗi số đầu tiên nếu thoả mãn nhỏ hơn hoặc bằng 12 thì nó sẽ tự gán đó là tháng còn nếu lớn hơn thì nó sẽ coi đó là ngày và xét tiếp chuối tiếp theo nếu nó thoả mãn là ngày hay tháng để xây dựng kiểu dữ liệu thời gian, còn nếu các điều kiện đó không thoả mãn thì thông báo lỗi.
Debug.Print Format("10/1/2005", "mmm-dd-yyyy")
Debug.Print Format("1/10/2005", "mmm-dd-yyyy")

Kết quả buồn cười chưa
Oct-01-2005
Jan-10-2005
Nếu định dạng hệ thống bạn để là mm/dd/yyyy
còn để định dạng hệ thống là dd/mm/yyyy thì kết quả đúng là cái ta cần
Chúng ta có thể thấy rõ, vậy nếu chúng ta sử dụng cấu hình thời gian hệ thống là mm/dd/yyyy rồi yêu cầu người dùng nhập vào chuỗi như vậy thì sẽ không có vấn đề gì cả. Tuy nhiên, điều naỳ sẽ gây trở ngại cho người dùng Việt nam. Vì vậy tôi xin tạm giới thiệu một cách khá củ chuối để làm sao sử dụng dữ liệu thời gian một cách nhuần nhuyễn - tất nhiên ở cấp độ cò con của chúng ta thôi. Các nhà sản xuất phần mềm họ sẽ làm khác nhiều - hiện đại và ngon hơn nhiều.
Yêu cầu của đầu vào là: Nhập dữ liệu dạng dd/mm/yyyy qua textbox
Yêu cầu đầu ra là: cung cấp dữ liệu đúng để xử lý – ví dụ trong query chẳng hạn.
Để làm được điều này bạn cần 2 công đoạn
  • tách ra các chuỗi ngày tháng và năm riêng
  • Chuyển đổi các chuỗi đã xắp xếp hợp lý sang kiểu ngày tháng.
Các bạn nên thiết kế phần tách chuỗi thành dạng hàm để thực hiện cho tiện. Xét thủ tục ví dụ dưới đây của tôi nhé


Function GetDateString(RawString As String, Optional DateSeparator As String = "/") As Date
' Gia dinh kieu dau vao cua du lieu luon la dd/mm/yyyy
' o day toi dung DateSeparator de co the thay / thanh - hoac bat ky kieu phan cach nao khac
Dim StrDate As String
Dim StrMonth As String
Dim StrYear As String
Dim i As Integer, x As Integer
' tach doan chuoi dau tien chua ngay
x = InStr(RawString, DateSeparator)
StrDate = Mid(RawString, 1, x - 1)
' rut ngan doan chuoi dang xu ly
RawString = Mid(RawString, x + 1)
x = InStr(RawString, DateSeparator)
StrMonth = Mid(RawString, 1, x - 1)
' tach doan chuoi chua ngay
StrYear = Mid(RawString, x + 1)
' dua ra chuoi chuan va chuyen sang kieu du lieu ngay thang
GetDateString = CDate(StrMonth & DateSeparator & StrDate & DateSeparator & StrYear)
End Function


Khi gọi hàm chúng ta chỉ cần gọi như sau:
GetDateString([chuỗi đưa vào],|Kiểu phân cách|)
Các bạn có thể dùng cách này, tôi tin là sẽ có thể giải quyết được vài việc với kiểu dữ liệu thời gian…
Vậy tóm lại ta có thể yêu cầu người dùng nhập vào định dạng dữ liệu chuẩn và rồi sử dụng cách trên thì - chúng ta có thể bước qua được khó khăn này bất kể định dạng hệ thống về thời gian là gì. Cách tương tự cũng có thể áp dụng với kiểu định dạng số (chấm . và phẩy , - hihi) Củ chuối nhỉ...
Thế đã nhé - giờ tớ đi làm - nếu ai cần trao đổi thêm cứ YIM tớ paulsteigel
 
Sửa lần cuối:
L

lehongduc

Trung cấp
29/3/05
131
1
18
64
VietNam
Là bắt buộc đó các Bác ơi.

Đào Việt Cường nói:
Dear lehongduc,
---------------
Liệu có phải "bắt buộc phải tuân thủ" không bác?
Theo em hiểu thì các định dạng (format) và kiểu (type) không làm thay đổi giá trị (Value). Chúng ta đang truy vấn tới một giá trị thì cho dù có format ở định dạng nào, giá trị đó cũng không hề thay đổi. Kiểu dữ liệu Datetime thực chất là Numberic, nó không phụ thuộc vào định dạng dd/mm/yyyy.
Để truy vấn đến giá trị này thay vì sử dụng cập dấu nháy kép "" như biểu diễn trích xuất một chuỗi "String" thì ta sử dụng cặp dấu ## để biểu diễn giá trị kiểu thời gian #Datetime#. Hai cách biểu diễn này là để phân biệt String và Datetime. Ví dụ:
#31/5/2006# là một Datetime (chúng ta có thể #31/5/2006# +1 = #1/6/2006#), và:
"31/5/2006" là một String, chúng ta không thể "31/5/2006" +1 (is ERROR!).
Vì vấn đề này liên quan đến kiến thức cơ bản về MSA, nên em muốn mình không bị hiểu sai cơ bản, mong bác chỉ bảo thêm!:friend:
Bác Cường và các Bác thân mến,
Xin các Bác đọc đoạn trích dẫn sau đây nhé:
"... Use International Date Formats in SQL Statements [Access 2003 VBA Language Reference]

You must use English (United States) date formats in SQL statements in Visual Basic. However, you can use international date formats in the query design grid."
Nguồn: http://msdn.microsoft.com/library/d...vbaac11/html/achowSQLStringVBA_HV05187046.asp
Như vậy là rõ rồi các Bác ạ: bắt buộc đó.
 
Đào Việt Cường

Đào Việt Cường

Moderator
22/11/05
400
4
18
Khánh Hòa
Dear all,
-------
Trước hết xin được cám ơn những kinh nghiệm chia sẻ của các anh. Các kiến thức trên đây quả là vô cùng quan trọng.
Chủ đề ban đầu bàn về một lỗi truy vấn của bạn phamdinhhai (các bài viết phía trên được di rời từ chủ đề này), song giờ chúng ta lại đề cập đến vấn đề khác (truy vấn dữ liệu kiểu thời gian), em e sẽ lạc đề. Theo em thì nên mở một chủ đề khác để bàn về vấn đề này, vì thứ nhất nó quan trọng, thứ hai nó là kiến thức cơ bản, thứ ba có nhiều ý kiến đưa ra nhưng chưa được tổng hợp, nếu vấn đề này không được trao đổi sẽ dẫn đến có nhiều cách xử lý khác nhau, cần phải giúp mọi người chọn ra cách xử lý hợp lý nhất. Sau đây em xin tổng hợp lại các ý kiến để chúng ta thảo luận:
1- Note that the number signs (#) that denote the date values must be included in the string so that they are concatenated with the date value.
Chúng ta nên ghi nhớ rằng ký tự # dùng để biểu thị một giá trị thời gian. Nó dùng để phân biệt dd/MM/yyyy là một giá trị kiểu chuỗi hay giá trị kiểu thời gian. http://msdn.microsoft.com/library/de...HV05187046.asp nói rất rõ điều này.
2- You must use English (United States) date formats in SQL statements in Visual Basic.
Khi xây dựng một phát biểu SQL, VBA luôn biểu thị thời gian theo tiêu chuẩn Anh ngữ (United States). Có nghĩa là khi chúng ta truy vấn một đối tượng kiểu thời gian thì đối tượng đó luôn được SQL mặc định ở dạng thức mm/dd/yyyy. Điều này cũng giải thích tại sao nếu chúng ta cấu hình thời gian hệ thống là mm/dd/yyyy rồi yêu cầu người dùng nhập vào chuỗi theo định dạng dd/mm/yyyy thì sẽ không có vấn đề gì cả. Và ngược lại, khi chúng ta cấu hình thời gian hệ thống là dd/mm/yyyy thì người dùng phải nhập ngày tháng theo định dạng mm/dd/yyyy.
Đến đây chúng ta hiểu sẽ phải xây dựng SQL như thế nào để VBA truy vấn đúng theo ý muốn của người dùng? Có nhiều cách để làm được điều này, song giải thuật chung như bác paulsteigel đã nêu: tách ra các chuỗi ngày tháng và năm riêng sau đó convert giá trị thành kiểu ngày tháng. Tuy nhiên nếu phải xây dựng cả một thủ tục để làm việc này thì khá... tốn kém! Chúng ta hoàn toàn có thể chuyển đổi một cách "thủ công" như sau:
Dim dtToday as Date
dtToday = Month(Date) & "/" & Day(Date) & "/" & Year(Date)
Cách này sẽ cho chúng ta thấy việc phải chuyển đổi giá trị kiểu thời gian từ định dạng dd/mm/yyyy sang định dạng mm/dd/yyyy như thế nào. Với kỹ thuật có kinh nghiệm hơn, việc chuyển đổi này có thể sử dụng hàm format với chuỗi định dạng là "mm/dd/yyyy" như bác lehongduc đã nêu.
Em cho rằng đây là những kiến thức hết sức cơ bản và cũng rất quan trọng cho những ai làm quen với MS Access cũng như muốn làm việc thành thạo với ngôn ngữ SQL. Vì vậy, theo em các bài viết liên quan đến vấn đề này nên được tập hợp lại thành một chủ đề "Datetime format trong SQL-VBA" để mọi người dễ theo dõi và không hỏi lại những vấn đề mà chúng ta đã trao đổi nữa!
 
Sửa lần cuối:

Xem nhiều

Webketoan Zalo OA