สอบถามปัญหา access query timeout expired sql serve
กระทู้เก่าบอร์ด อ.Yeadram

 16,578   25
URL.หัวข้อ / URL
สอบถามปัญหา access query timeout expired sql serve

สอบถามปัญหา access query timeout expired sql server 2008 ต้องแก้ไขอย่างไรดีค่ะ

25 Reply in this Topic. Dispaly 2 pages and you are on page number 1

1 @R17852
ไม่ได้ใช้นะครับ แต่ตอบตามหลักการแล้วกัน คือต้องดูว่า error message ระบุว่า timeout นี้เกิดจากส่วนไหน เกิดจาก sql server เลย หรือจาก ole db หรือ odbc หรือ dao   เกิดส่วนไหนก็ต้องไปปรับที่ส่วนนั้นหน่ะครับ
2 @R17854
odbc ค่ะ ต้องไปปรัป ตรงไหนค่ะ
3 @R17857
ถ้าคุณใช้ Access Query object ให้คุณเปิดใน design view แล้วไปคลิกพื้นที่ว่างๆที่ไหนในหน้าต่าง design view ก็ได้ กด F4 เพื่อดู property sheet ให้แก้ที่บรรทัด ODBC Timeout ให้เป็นศูนย์

ถ้าคุณสร้าง sql statement ใน VBA โค้ด ให้สั่ง CurrentDB.QueryTimeout = 0 ก่อนสั่งเปิด .OpenRecordset method หรือก่อน .Execute method
4 @R18149
รบกวนด้วยครับ ตอนนี้มีปัญหาเดียวกันครับ
ตอนนี้ถ้ามีการ Update ข้อมูลปริมาณมากๆ จะเกิด Runtime error ตัวนี้ครับ Timeout expired

จากที่ค้นหาข้อมูลมาวิธีที่ง่ายสุดคือ เปลี่ยน Code vba ให้เป็น Query object แล้วตั้งค่าใน Propoties ให้เป็น 0

ซึ่งของผมมีปัญหากับ Function Buildfilter ที่ไม่รู้วิธีที่จะเอาไปใช้กับ Query object ครับ

*Function นี้เอาไว้สร้าง where จาก Criteria ที่ User กรอกจากหลายๆ Textbox ที่มีครับ

Public Function BuildFilterFCTN() As Variant
Dim varWhere As Variant
varWhere = "([02WHTInvoiceTbl].[Record_Status] = " & "'" & recordstatus & "')" & " And "
If bucontract = "" Then
    Else
    varWhere = varWhere & "([02WHTInvoiceTbl].[Contract_No] = '" & bucontract & "') AND "
    End If
    If payer = "" Then
    Else
    varWhere = varWhere & "([02WHTInvoiceTbl].[Customer_Name] like '*" & payer & "*' " & ") AND "
    End If
    If amt = "0.00" Then
    Else
    varWhere = varWhere & "([02WHTInvoiceTbl].[WHT] = " & amt & ")" & " AND "
    End If
      If appcode = "" Then
     Else
     varWhere = varWhere & "([02WHTInvoiceTbl].[App_Code] = '" & appcode & "')" & " AND "
     End If
             If IsNull(varWhere) = True Then
    varWhere = ""
    Else
        If Right(varWhere, 5) = " AND " Then
        varWhere = Left(varWhere, Len(varWhere) - 5)
        End If
    End If
    BuildFilterFCTN = varWhere
End Function


โดยการเอาไปใช้ Update จะใช้แบบนี้ครับ

        SQL = "UPDATE [02WHTInvoiceTbl] " & _
        "SET [WHT_Base_Claim] = '0.00' " & _
        ",[WHT_Claim] = '0.00' " & _
        " WHERE " & BuildFilterUser
        DoCmd.RunSQL SQL

ซึ่งถ้าเป็นคำสั่ง CurrentDB.QueryTimeout = 0 เท่าที่เอาไปลองไม่เกิดอะไรขึ้นครับผมเข้าใจว่าโค้ดส่วนนี้เป็นคำสั่ง SQL ที่ไม่ได้ปะกาศ Recordset เลยใช้คำสั่งนี้ไม่ได้ครับ

สอบถามครับถ้าผมจะเ้ปลี่ยนคำสั่ง Update Field 2 Field นี้ โดยมี Criteria WHERE ด้วย Function BuildFilter ตัวนี้ให้เป็น Query Object จะต้องทำอย่างไรครับ หรือว่าผมสามารถกำหนดค่า timeout ได้เลยโดยใช้โค้ดได้เลยครับ หรือว่าผมต้องเปลี่ยนโค้ดส่วนนี้ไปใช้วิธีประกาศ RecordSet
เช่น
        Dim rs00 As DAO.Recordset, SQL00 As String
        'Check for 1st roll of BUClaim_Log
        SQL00 = "SELECT * FROM [04Transaction_Code] WHERE [TXN Code] = " & tcode & " ;"
            Set rs00 = CurrentDb.OpenRecordset(SQL00)
แล้วจึงประกาศคำสั่ง CurrentDB.QueryTimeout = 0 ก่อนที่จะสั่ง Update รายการจะได้มั้ยครับ
วิธีไหนที่เหมาะสมกับการปรับใช้งานครับ

ขอบคุณครับ
5 @R18150
CurrentDB.QueryTimeout = 0
CurrentDB.Execute "UPDATE [02WHTInvoiceTbl] SET [WHT_Base_Claim] = '0.00' ,[WHT_Claim] = '0.00' WHERE " & BuildFilterUser
6 @R18153
ขอบคุณครับอาจารย์
ใช้งานได้ตามที่ต้องการครับ
มีข้อสงสัยเพิ่มเติมสองข้อครับ
1. ส่วนของ CurrentDB.QueryTimeout = 0 ต้องประกาศทุกครั้งก่อนจะสั่ง Execute เลยมั้ยครับ หรือต้องประกาศทุกครั้ง

2. ผมลองใช้กับอีกหน้าจอที่คล้ายกัน(ทำไว้สำหรับ User อีกสิทธ์นึงใช้งานเหมือนกัน) แต่เมื่อลองใช้งานพบว่า
Error 3157: "ODBC - update on a linked table failed (ผมทดลองกับข้อมูลเดียวกับที่ทำผ่านในหน้าจอเก่า

-ตอนนี้กำลังไล่ดูโค้ดว่ามีส่วนไหนที่ไม่ถูกบ้างครับ ตอนนี้ที่ดูพบว่าโค๊ดเดียวกันจะเป็นกรณีไหนได้บ้างครับ(กำลังไล่ดูส่วนอื่นๆ ถ้าพบจะมาบอกครับ)
7 @R18155
ตอนนี้กลายเป็น Error 3157: "ODBC - update on a linked table failed ทั้งสองอร์มเลยครับ (เฉพาะกรณีทำงานข้อมูลเยอะๆ) หรือจะเป็นเพราะมีคนใช้งานหลายคนครับ
8 @R18156
1. ไม่แน่ใจครับ แต่ประกาศไว้ทุกครั้งก็ดี

2. เวลาที่เราเข้าถึงข้อมูล ลำดับของตัวจัดการข้อมูลจะมีหลายๆชั้น แล้วแต่เทคโนโลยีที่เราเลือกใช้เพื่อเข้าถึงฐานข้อมูล ตย.คร่าวๆเช่น เราเขียนโปรแกรมโดยเรียกใช้ DAO และมี ODBC เพื่อเชื่อมต่อไปยัง MS SQL SERVER   เมื่อมี error เกิดขึ้น มันมีความเป็นไปได้ว่าเกิด error มาจากตัวจัดการข้อมูลในระดับที่อยู่ต่ำๆลงไป ดังนั้นเพื่อหาว่าจริงๆแล้วมี error อะไรที่เกิดขึ้นบ้าง เราต้องวนอ่านจาก Errors collection (ของ DAO) ซึ่งจะเป็นตัวเก็บ error ที่มาจากแต่ละลำดับชั้นต่างๆเอาไว้ ลำดับแรกที่อ่านได้ใน Errors collection (Errors(0)) จะมาจาก error ลำดับล่างสุดของตัวจัดการข้อมูล (นั่นคือ MS SQL SERVER) ถ้าเราอ่านจาก Err object (ของ VBA) เฉยๆ มันจะมีค่าเท่ากับเราอ่านจาก Errors collection ลำดับสุดท้าย (Errors(Errors.count - 1)) ซึ่งมันอาจไม่ได้บอกอะไรได้ละเอียดมากไปกว่า "ฉันอัพเดตไม่ได้" เท่านั้นเอง

โครงสร้างของโปรแกรมก็จะเป็นลักษณะนี้

Private Sub xxxxxx( )
   Dim myErr As DAO.Error

   On Error GoTo ErrRtn
          
   CurrentDb.Execute .....
          
ExitRtn:
   Exit Sub

ErrRtn:
   For Each myErr In DAO.Errors
       MsgBox wErr.Source & ", " & wErr.Number & ", " & wErr.Description
   Next
   Resume ExitRtn
End Sub
9 @R18159
แก้จาก MsgBox wErr.Source & ", " & wErr.Number & ", " & wErr.Description

เป็น MsgBox myErr.Source & ", " & myErr.Number & ", " & myErr.Description
10 @R18160
ลองแล้วครับอาจารย์

กลายเป็นว่า timeout expired ครับ คือขึ้นว่า ODBC.Database, 0, [Microsoft][ODBC SQL Server Driver] Timeout expired ซึ่งเหมือนก่อนที่จะกำหนด currentDB.QueryTimeout = 0 ครับ

จากนั้นจึงขึ้น DAO.Database, 3157, ODBC Update linked table failed.

แสดงว่าจริงๆแล้วมันคือ Timeout expired เลยทำให้การ update failed ใช่มั้ยครับ

โค้ดที่เกิด Error ครับ

CurrentDb.QueryTimeout = 0
CurrentDb.Execute "UPDATE [02WHTInvoiceTbl] " & _
        "SET [Mark] = '-1' " & BuildFilterUser

ส่วนนี้เป็นการกำหนด select all data ที่ดึงมาทำงานครับ

รบกวนอาจารย์อีกครั้งครับ
11 @R18164
เพิ่มเติมครับ
ก่อนหน้าที่จำทำการ select all เมื่อเปิดฟอร์ม (Form Load) จะมีการ Update ข้อมูลก่อนครับ

CurrentDb.QueryTimeout = 0
CurrentDb.Execute "UPDATE [02WHTInvoiceTbl] " & _
        "SET [WHT_Base_Claim] = [WHT_Base_Outstanding] " & _
        ",[WHT_Claim] = [WHT_Outstanding] " & _
        ",[Username] = '" & user & "' " & BuildFilter

ซึ่งปริมาณข้อมูลเท่ากับตอนที่ select all ครับแต่ error เฉพาะ select all
*ส่วนการทำงานอื่นๆยังไม่ได้ทดสอบครับ การบันทึกข้อมูลจำมาอีก 5 - 6 ขั้นตอนครับ
12 @R18165
เท่าที่อ่านดูก็ งงๆ นะครับ แต่เอาเป็นว่าลองตรวจสอบคำสั่งดูให้ดีก่อนนะครับว่าเขียนโค๊ดถูกต้องจริงๆ เพราะการที่เราเขียนคำสั่งให้ค่า Data Type ผิด เมื่อทำการ Update ลงฐานข้อมูล Server จะปฏิเสธการ Update ของเรา นั่นก็ทำให้เกิด Timeout expired ได้เช่นกัน
ดูจากโค๊ดที่เห็น
"SET [Mark] = '-1' " ไม่น่าจะใช้ได้จริงนะครับ

ถ้ารูปแบบ String
"SET [Mark] = '1' " และ "SET [Mark] = '' "
ถ้ารูปแบบ Integer
"SET [Mark] = 1 " และ "SET [Mark] = 0 "
ถ้ารูปแบบ Boolean
"SET [Mark] = True " และ "SET [Mark] = False "

ลองตรวจสอบโค๊ดทั้งหมดว่าเขียนได้ถูกต้องหรือเปล่าก่อนครับ เท่าที่อ่านคิดว่าไม่น่าใช่ที่เน็ทเวิร์ค
13 @R18166
mark ตัวนี้ถูกแล้วครับ

จากเดิมเป็น field yes/no แต่ตอนที่ขึ้น sql server มันมีปัญหาต้องเปลี่ยนเป็น text ครับทำให้เวลาใช้งานจะเป็น "-1" = yes , "0" = no ครับ
14 @R18167
ตอนนี้กรณีที่ใช้งานกับข้อมูลปริมาณไม่มาก เช่นใช้เงื่อนไขที่แคบ จะใช้ได้ไม่มีปัญหาครับ
15 @R18169
อื่ม ตกลงปัญหาคุณติดอะไรกันแน่ ตรงไหนแก้ได้แล้วตรงไหนยังไม่ได้
สังเกตุอีกที่นึงนะครับตรง
    CurrentDb.QueryTimeout = 0
ผมว่ามันใช้ไม่ได้จริงอ่ะครับ การกำหนด QueryTimeout มันกำหนดตรงๆแบบนี้ไม่ได้อ่ะครับ ทดสอบดู

Sub Test()
    CurrentDb.QueryTimeout = 0
    MsgBox CurrentDb.QueryTimeout
End Sub

มันจะเป็น 60 เหมือนเดิม
มันต้องกำหนดโดยผ่านการประกาศตัวแปรแบบนี้มั้งครับ

Sub Test()
    Dim Mydb As DAO.Database
    Set Mydb = CurrentDb
    Mydb.QueryTimeout = 0
    MsgBox Mydb.QueryTimeout
End Sub

Timeout ถึงจะเป็น 0 ตามที่กำหนด
ลองปรับใช้ดูนะครับ
16 @R18170
ขอบคุณครับอาจารย์

ที่ตอนทดสอบตอนใช้
CurrentDb.QueryTimeout = 0
แล้วผ่านตอนนั้นทดสอบแล้วพบว่าการทำการ update แต่ละครั้งจับเวลาดูพบว่าแม้การทำงานกว่า 20 นาทียังไม่ติด timeout ครับ แต่ผมไม่ได้ทำสอบค่าโดยให้แสดงผล msgbox currentdb.querytimeout ครับ

17 @R18171
ตอนนี้ผมไปทดสอบมาแล้วครับ

ยังติด timeout expired อยู่เหมือนเดิมครับ

Dim Mydb As DAO.Database
Set Mydb = CurrentDb
Mydb.QueryTimeout = 0
Mydb.Execute "UPDATE [02WHTInvoiceTbl] " & _
        "SET [Mark] = '-1' " & BuildFilterUser

ซึ่งเมื่อ Check ค่า timeout ของ Mydb จะแสดงผลเป็น 0 แล้วครับ

ถ้าผมจะเปลี่ยน ไปใช้ query object แล้วส่วน buildfilterUser นี้ผมจะต้องสร้างออกมาแบบไหนครับ
ที่เคยลองยังไม่สามารถทำได้เลยครับ

BuildFilterUser
มาจากใน form มีหลาย textbox ที่เป็น Criteria ให้ user เลือกใช้ในการค้นหาข้อมูลครับซึ่งไม่จำเป็นต้องกรอกทุกอย่าง ผมจุงใช้ Function BuildFilterUser มาตัดคำ(ที่จะเป็น Where ... ของ SQL ครับ แล้วจึงเอามาต่อท้ายคำสั่ง Update หรือ set recordsource

ผมคิดวิธีเอาไปใช้กับ Query Object ไม่ออกครับว่าถ้าไม่กรอก text1 แล้วไม่ต้องใช้ Field1 ใน Criteria ครับถ้ามีแนวทางรบกวนหน่อยครับ

ขอบคุณอาจารย์ที่สละเวลาช่วยดูให้ครับ
18 @R18172
อื่ม ค่อยๆลองเปลี่ยนจาก 0 เป็น 120, 180 ดูครับ ซึ่งจริงๆแล้วควรปรับที่ตัวเครื่อง Server ด้วยนะครับ

Timeout Expired เป็นปัญหาที่เจอกันค่อนข้างบ่อยครับ กับการคิวรี่ข้อมูลจำนวนมากๆผ่านทาง Server ซึ่งหมายถึงคำสั่ง sql ที่ส่งไป execute มันใช้เวลานานเกินค่าที่กำหนดให้รอเลยเกิด Error ฟ้องขึ้นมา ตัวอย่างง่าย ๆ เช่น default timeout ของโปรแกรมคุณ สมมติเป็น 60 วินาที เมื่อมีการส่ง sql ไปให้ sql server ประมวลผลแล้ว ตัวโปรแกรมของคุณจะรอเป็นเวลา 60 วินาที ซึ่งถ้ารอครบแล้วไม่มีผลลัพธ์ จาก sql server กลับมา มันก็จะเกิด error ว่า timeout expired

ซึ่งการจะลดการเกิด timeout expired นี้อยู่ที่หลายอย่างและต้องเข้าใจพอสมควรอ่ะครับ เช่น
- การ Optimized Query คือการปรับแต่ง/แก้ไข query ให้ใช้ resource ของเครื่องน้อยที่สุด แต่ยังได้ผลลัพธ์และความเร็วในระดับที่พอใจ ส่วนมากเราจะต้องมาไล่ดู query ยาว ๆ หรือที่มีซ้อนกันเยอะ ๆ หลายชั้น เพื่อดูว่าเหมาะสมหรือยังเช่น
ของเดิม
Select colA, colB, colC, ...
From table1
Where colA = 'AAA'
And colA = 'ABB'
And colA = 'ACC'
สามารถ optimized เป็นดังนี้
Select colA, colB, colC, ...
From table1
Where colA In('AAA', 'ABB', 'ACC')

- การพยายามเขียนคำสั่งการประมวลผลที่ตัวเครื่องลูกให้มากเพื่อลดการทำงานของเครื่องแม่

- ความเสถียรของระบบเน็ทเวิร์คเอง และการออกแบบเพื่อลดปริมาณการส่งผ่านข้อมูลให้กับ Server

- และอีกหลายอย่างมากครับ ผมว่าคงต้องค่อยๆลองศึกษาปรับแต่งดูครับ ผมเองสามารถช่วยได้แบบจำกัด ต้องขออภัยด้วยครับ
19 @R18173
และจากที่คุณบอกว่า

mark ตัวนี้ถูกแล้วครับ
จากเดิมเป็น field yes/no แต่ตอนที่ขึ้น sql server มันมีปัญหาต้องเปลี่ยนเป็น text ครับทำให้เวลาใช้งานจะเป็น "-1" = yes , "0" = no ครับ

ผมก็ไม่ทราบนะว่าปัญหาคือไร แต่นี่เป็นอีกอย่างที่ขัดหลักการณ์ Optimized Query คือเพียงแค่คุณอยาก Select แต่กลับใช้ Data type เป็น Text ซึ่งมันต้องใช้จำนวนบิตในการส่งข้อมูลมากกว่า Boolean มากๆ นี่ก็อาจเป็นสาเหตุที่ทำให้เกิด Timeout ได้ครับ ลองพยายามแก้กลับไปใช้เป็น Boolean ให้ได้ครับ
20 @R18174
ลอง

Private Sub xxxxxx( )

Dim myErr As DAO.Error
Dim myDB As DAO.Database
Dim myQdf As DAO.QueryDef

On Error GoTo ErrRtn

Set myDB = CurrentDb
myDB.QueryTimeout = 0

Set myQdf = myDB.CreateQueryDef("", "UPDATE [02WHTInvoiceTbl] SET [Mark] = '-1' " & BuildFilterUser)
myQdf.Execute dbFailOnError

...
...
...

ExitRtn:
   On Error Resume Next
   myQdf.Close: Set myQdf = Nothing
   Exit Sub

ErrRtn:
   For Each myErr In DAO.Errors
       MsgBox myErr.Source & ", " & myErr.Number & ", " & myErr.Description
   Next
   Resume ExitRtn
End Sub
@ ประกาศใช้งานเว็บบอร์ดใหม่ => บอร์ดเรียนรู้ Access สำหรับคนไทย
แล้วจะใส่ลิ้งอ้างอิงมาที่โพสต์เก่านี้หรือไม่ก็ตามสะดวกครับ
Time: 0.2329s