پرس و جوهای SQL چند رکوردی (Multiple Record SQL Queries)
در نهایت، بیایید به الگوی اجرای دستورات SQL که چندین سطر را برمیگرداند، نگاهی بیندازیم. من این را با بهروزرسانی متد SnippetModel.Latest() برای برگرداندن ده قطعه اخیراً ایجاد شده (Recently Created Snippets) (تا زمانی که منقضی نشدهاند) با استفاده از پرس و جوی SQL (SQL Query) زیر نشان خواهم داد:
SELECT id, title, content, created, expires FROM snippets WHERE expires > UTC_TIMESTAMP() ORDER BY id DESC LIMIT 10
برای این کار، نیاز به اجرای یک پرس و جوی SQL (SQL Query) با استفاده از محدودیت تعداد نتایج (Result Limit) داریم.
فایل internal/models/snippets.go را باز کنید و کد زیر را اضافه کنید:
package models ... func (m *SnippetModel) Latest() ([]Snippet, error) { // Write the SQL statement we want to execute. stmt := `SELECT id, title, content, created, expires FROM snippets WHERE expires > UTC_TIMESTAMP() ORDER BY id DESC LIMIT 10` // Use the Query() method on the connection pool to execute our // SQL statement. This returns a sql.Rows resultset containing the result of // our query. rows, err := m.DB.Query(stmt) if err != nil { return nil, err } // We defer rows.Close() to ensure the sql.Rows resultset is // always properly closed before the Latest() method returns. This defer // statement should come *after* you check for an error from the Query() // method. Otherwise, if Query() returns an error, you'll get a panic // trying to close a nil resultset. defer rows.Close() // Initialize an empty slice to hold the Snippet structs. var snippets []Snippet // Use rows.Next to iterate through the rows in the resultset. This // prepares the first (and then each subsequent) row to be acted on by the // rows.Scan() method. If iteration over all the rows completes then the // resultset automatically closes itself and frees-up the underlying // database connection. for rows.Next() { // Create a new zeroed Snippet struct. var s Snippet // Use rows.Scan() to copy the values from each field in the row to the // new Snippet object that we created. Again, the arguments to row.Scan() // must be pointers to the place you want to copy the data into, and the // number of arguments must be exactly the same as the number of // columns returned by your statement. err = rows.Scan(&s.ID, &s.Title, &s.Content, &s.Created, &s.Expires) if err != nil { return nil, err } // Append it to the slice of snippets. snippets = append(snippets, s) } // When the rows.Next() loop has finished we call rows.Err() to retrieve any // error that was encountered during the iteration. It's important to // call this - don't assume that a successful iteration was completed // over the whole resultset. if err = rows.Err(); err != nil { return nil, err } // If everything went OK then return the Snippets slice. return snippets, nil }
استفاده از مدل در هندلرهای ما (Using the Model in our Handlers)
به فایل cmd/web/handlers.go برگردید و هندلر home را بهروزرسانی کنید تا از متد SnippetModel.Latest() استفاده کند و محتوای قطعه را به یک پاسخ HTTP بریزد. فعلاً فقط کد مربوط به رندر قالب را کامنت کنید، به این صورت:
package main import ( "errors" "fmt" // "html/template" "net/http" "strconv" "snippetbox.letsgofa.net/internal/models" ) func (app *application) home(w http.ResponseWriter, r *http.Request) { w.Header().Add("Server", "Go") snippets, err := app.snippets.Latest() if err != nil { app.serverError(w, r, err) return } for _, snippet := range snippets { fmt.Fprintf(w, "%+v\n", snippet) } // files := []string{ // "./ui/html/base.tmpl", // "./ui/html/partials/nav.tmpl", // "./ui/html/pages/home.tmpl", // } // ts, err := template.ParseFiles(files...) // if err != nil { // app.serverError(w, r, err) // return // } // err = ts.ExecuteTemplate(w, "base", nil) // if err != nil { // app.serverError(w, r, err) // } } ...
اگر اکنون برنامه را اجرا کنید و به http://localhost:4000 در مرورگر خود بروید، باید پاسخی مشابه این دریافت کنید:
واژهنامه اصطلاحات فنی
| اصطلاح فارسی | معادل انگلیسی | توضیح |
|---|---|---|
| پرس و جوهای SQL چند رکوردی | Multiple Record SQL Queries | دستورات SQL که چندین رکورد را از پایگاه داده بازیابی میکنند |
| قطعه اخیراً ایجاد شده | Recently Created Snippet | قطعههای کدی که به تازگی در سیستم ذخیره شدهاند |
| پرس و جوی SQL | SQL Query | دستوری برای درخواست یا تغییر داده در پایگاه داده |
| محدودیت تعداد نتایج | Result Limit | تعیین حداکثر تعداد رکوردهایی که باید بازگردانده شوند |
| مجموعه نتیجه | Result Set | مجموعهای از رکوردها که توسط یک پرس و جو برگردانده میشوند |
| اتصال پایگاه داده زیرین | Underlying Database Connection | اتصال فیزیکی به پایگاه داده که برای اجرای دستورات استفاده میشود |
| مرتبسازی نتایج | Result Sorting | ترتیببندی نتایج بر اساس یک یا چند فیلد |
| فیلترینگ نتایج | Result Filtering | محدود کردن نتایج بر اساس شرایط خاص |
| پیمایش نتایج | Result Iteration | مرور و پردازش تدریجی نتایج یک پرس و جو |