1

フォームを同じページに送信し、送信された値を表示できますが、送信/投稿された値を挿入しようとすると、構文に苦労しています。変数として値にアクセスするにはどうすればよいですか? この行の正しい書き方と、挿入クエリをどこに持ち込めばよいでしょうか?

(クエリ実行 sql-exp
            "insert into students(name) values ( '`post-body a-post')")

以下のコードで値を表示できます。

; render-post: post -> xexpr
; 投稿を消費し、投稿の xexpr フラグメントを生成します。
(define (render-post a-post)
  `(div ((class "post"))
        "題名 : "
        ,(post-title a-post)
        (p ,"投稿 : "
         ,(post-body a-post))))


; render-posts: ブログ -> xexpr
; ブログを消費し、xexpr フラグメントを生成します
; すべての投稿の。
(define (render-posts a-blog)
  `(div ((class "posts"))        
        ,@(map render-post a-blog)))
4

1 に答える 1

1

query-execのドキュメントの2番目の例は、パラメーターを受け取るデータベースクエリを実行する方法を示しています。

たとえば、と列を持つfoodテーブルがあると仮定すると、そのテーブルに挿入できる関数を記述できます。namecalories

;; insert-food!: database-connection string number -> void
;; Inserts an element into the food table.
(define (insert-food! conn name cals)
  (query-exec conn
              "insert into food (name, calories) values ($1, $2)" 
              name
              cals))

データベースがPostgreSQLまたはプレースホルダーなどの使用をサポートするデータベースであり、それらのプレースホルダーの値を追加の引数としてに渡すことを前提として、パラメーター化されたクエリを使用しています。$1$2query-exec

外部から入力を受け取り、それを使用してSQLクエリを作成する場合は、パラメータ化されたクエリの使用方法を知っている必要があります。そうしないと、データベースの安全性が危険にさらされます。変数の値をすべて1つのクエリ文字列に補間する単一の文字列をフォーマットしようとしないでください。非常に間違ってプログラムをSQLインジェクションのエクスプロイトにさらす可能性があります。代わりに、これらの値を個別の引数としてに渡しますquery-exec

また、上記の関数はWebサーバーのコンテキストで使用する必要はないことに注意してください。たとえば、単体テストのコンテキストで使用できます。この関数をWebサーブレットで使用せずにテストすることをお勧めします。このようなもの:

#lang racket

(require db)

;; We want to export the following functions to outside clients.
(provide [struct-out foo]
         insert-food!
         get-foods!)


;; A food is a:
(struct food (name ;; string
              cals) ;; number
  #:transparent)


;; insert-food!: database-connection food -> void
;; Inserts an element into the food table.
(define (insert-food! conn a-food)
  (query-exec conn
              "insert into food (name, calories) values ($1, $2)" 
              (food-name a-food)
              (food-cals a-food)))


;; get-foods!: database-connection -> (listof food)
;; Get a list of the foods in the database.
(define (get-foods! conn)
  (for/list ([(name cal)
              (in-query conn "select name, calories from food")])
    (food name cal)))


(module+ test
  (require rackunit)
  ;; Internal test.  We'll use an in-memory SQLite database.
  (define conn (sqlite3-connect #:database 'memory))
  (query-exec conn "create table food (name string, calories double)")

  ;; Initially, it should be empty.
  (check-equal? (get-foods! conn) '())

  ;; Now let's add a food:

  ;; http://www.eiyoukeisan.com/JapaneseFoodCalorie/zryouri/misoramen.html
  (insert-food! conn (food "miso ramen" 56000.0))

  ;; Can we get it back?
  (check-equal? (get-foods! conn) (list (food "miso ramen" 56000.0))))

これで、DrRacketでこのファイルを実行することにより、これらのデータベース機能の機能をテストできます。それらが確実に機能することがわかったら、Webサーブレットなどのさまざまなコンテキストでそれらを使用できます。

HTTPリクエストハンドラと同じ場所でこれをすべて実行しようとすると、間違ったアプローチになる可能性があります。データモデル、データベース操作をHTTPリクエストハンドラーとは別のモジュールに配置する必要があります。そうしないと、データモデルのテストが非常に困難になるリスクがあります。これが、 ContinueWebサーバーチュートリアルが「モデル」を個別のモジュールとして抽出することについて説明するのに邪魔にならない主な理由です。

于 2012-12-17T21:41:35.987 に答える