构造要插入数据库的SQL查询

时间:2012-12-13 18:54:48

标签: forms racket

我已将表单提交到同一页面,我可以显示提交的值,但是当我尝试插入提交/发布的值时,我正在努力学习语法。如何将值作为变量访问?编写此行的正确方法是什么?我在哪里引入插入查询?

(query-exec sql-exp
            "insert into students(name) values ( '`post-body a-post')")

我可以使用以下代码显示值:

; render-post: post -> xexpr
; Consumes a post, produces an xexpr fragment of the post.
(define (render-post a-post)
  `(div ((class "post"))
        "Title : "
        ,(post-title a-post)
        (p ,"Post : "
         ,(post-body a-post))))


; render-posts: blog -> xexpr
; Consumes a blog, produces an xexpr fragment
; of all its posts.
(define (render-posts a-blog)
  `(div ((class "posts"))        
        ,@(map render-post a-blog)))

1 个答案:

答案 0 :(得分:0)

documentation for query-exec中的第二个示例显示了如何执行接收参数的数据库查询。

例如,假设我们有一个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))

我们正在使用parameterized query,假设数据库是PostgreSQL或支持使用占位符$1$2等的数据库,并将这些占位符的值作为附加值传递query-exec的参数。

如果您正在从外部世界获取输入并使用它构建SQL查询,那么应该知道如何使用参数化查询,否则您将面临数据库安全的风险。 尝试格式化单个字符串,将所有变量的值插入到一个查询字符串中:您可能会错误地将其打开并将程序打开到SQL injection漏洞。相反,将这些值作为不同的参数传递给query-exec

另请注意,上述功能不需要在Web服务器的上下文中使用:例如,它可以在unit testing的上下文中使用。您可能想要来测试此函数,而无需在Web servlet中使用它。像这样:

#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 servlet。

尝试在与HTTP请求处理程序相同的位置执行此操作可能是错误的方法。您希望数据模型(数据库操作)与HTTP请求处理程序位于一个单独的模块中,否则可能会使数据模型难以测试。这就是Continue web-server tutorial不遗余力地将“模型”作为一个单独的模块提取的主要原因。