【问题标题】:Constructing an SQL query to insert into a database构造要插入数据库的 SQL 查询
【发布时间】:2012-12-13 18:54:48
【问题描述】:

我已将表单提交到同一页面,并且能够显示提交的值,但是当我尝试插入提交/发布的值时,我在语法上遇到了困难。如何将值作为变量访问?写这行的正确方法是什么?我在哪里引入插入查询?

(查询-exec sql-exp “插入学生(姓名)值('`post-body a-post')”)

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

;渲染发布:发布-> xexpr ;使用帖子,生成帖子的 xexpr 片段。 (定义(render-post a-post) `(div ((class "post")) “标题 : ” ,(后标题后) (p,“帖子:” ,(post-body a-post)))) ;渲染帖子:博客-> xexpr ;使用博客,生成 xexpr 片段 ;其所有职位。 (定义(render-posts a-blog) `(div((类“帖子”)) ,@(map render-post a-blog)))

【问题讨论】:

  • 您已经看过以下内容了吗? docs.racket-lang.org/continue/index.html
  • 是的,我做到了,但无法让它工作..我错过了一些东西..如果可能的话,请分享 1 个简单的例子..with 1.HTML 表单通过 POST 方法将表单提交给 servlet 2。打印发布值的 servlet
  • 您是否有防火墙和/或防病毒软件来阻止您的 Windows 机器上的端口?
  • 请通过“无法使其工作”来具体说明。要解决这样的技术问题,我们需要知道您所看到的内容,并且通过简单地报告故障,几乎没有内容可以重现您所看到的内容,或者知道您的意思。请明确点。您是否曾经运行过继续教程中的第一个示例?您收到了什么错误消息(如果有)?
  • 已经编辑了帖子并试图解释问题..抱歉之前没有具体说明,我希望有人能有一个非常简单的例子来满足类似的要求。

标签: forms racket


【解决方案1】:

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

例如,假设我们有一个包含namecalories 列的food 表,我们可以编写一个可以插入该表的函数。

;; 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 不遗余力地谈论将“模型”作为一个单独的模块提取出来的主要原因。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多