百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

2022年秋季CS50 Lecture7 SQL(2022年秋季赛gg的总淘汰数为?)

toyiye 2024-07-08 23:02 9 浏览 0 评论

  • Welcome!
  • Flat-File Database
  • Relational Databases
  • IMDb
  • JOINs
  • Indexes
  • Using SQL in Python
  • Race Conditions
  • SQL Injection Attacks
  • Summing Up

Welcome!


  • 在前几周,我们向你介绍了 Python,这是一种高级编程语言,它利用了我们在 C 语言中学到的相同构建块。
  • 本周,我们将继续更多与 Python 相关的语法。
  • 此外,我们将把这些知识与数据相结合。
  • 最后,我们将讨论 SQL结构化查询语言
  • 总的来说,本课程的目标之一是学习一般编程——而不仅仅是如何用本课程中描述的语言编程。

Flat-File Database


  • 正如你之前可能看到的那样,数据通常可以用列和表的模式来描述。
  • 像在Microsoft Excel和Google Sheets中创建的电子表格可以输出到csv或者 逗号分隔值 文件。
  • 如果你查看一个csv文件,你会注意到该文件是平面的,因为我们所有的数据都存储在由文本文件表示的单个表中。我们将这种形式的数据称为 平面文件数据库
  • Python附带对csv文件的本机支持。
  • 在终端窗口中,键入code favorites.py并编写代码,如下所示:
  # Prints all favorites in CSV using csv.reader

  import csv

  # Open CSV file
  with open("favorites.csv", "r") as file:

      # Create reader
      reader = csv.reader(file)

      # Skip header row
      next(reader)

      # Iterate over CSV file, printing each favorite
      for row in reader:
          print(row[1])
  • 请注意,csv库已导入。此外,我们创建了一个reader,将保存csv.reader(file)的结果。csv.reader函数从文件中读取每一行,在我们的代码中,我们将结果存储在reader中。print(row[1]),因此,将从favorites.csv文件中打印语言。
  • 你可以按如下方式改进代码:
  # Stores favorite in a variable

  import csv

  # Open CSV file
  with open("favorites.csv", "r") as file:

      # Create reader
      reader = csv.reader(file)

      # Skip header row
      next(reader)

      # Iterate over CSV file, printing each favorite
      for row in reader:
          favorite = row[1]
          print(favorite)
  • 请注意,favorite已存储,然后打印。另请注意,我们使用next函数跳到阅读器的下一行。
  • Python 还允许你按列表的键进行索引。按如下方式修改代码:
  # Prints all favorites in CSV using csv.DictReader

  import csv

  # Open CSV file
  with open("favorites.csv", "r") as file:

      # Create DictReader
      reader = csv.DictReader(file)

      # Iterate over CSV file, printing each favorite
      for row in reader:
          print(row["language"])
  • 请注意,此示例直接使用 print 语句中的language键。
  • 要计算csv文件中表达的最喜欢的语言的数量,我们可以执行以下操作:
  # Counts favorites using variables

  import csv

  # Open CSV file
  with open("favorites.csv", "r") as file:

      # Create DictReader
      reader = csv.DictReader(file)

      # Counts
      scratch, c, python = 0, 0, 0

      # Iterate over CSV file, counting favorites
      for row in reader:
          favorite = row["language"]
          if favorite == "Scratch":
              scratch += 1
          elif favorite == "C":
              c += 1
          elif favorite == "Python":
              python += 1

  # Print counts
  print(f"Scratch: {scratch}")
  print(f"C: {c}")
  print(f"Python: {python}")
  • 请注意,每种语言都使用if语句进行计数。
  • Python 允许我们使用字典来计算每种语言的counts。请考虑对代码进行以下改进:
  # Counts favorites using dictionary

  import csv

  # Open CSV file
  with open("favorites.csv", "r") as file:

      # Create DictReader
      reader = csv.DictReader(file)

      # Counts
      counts = {}

      # Iterate over CSV file, counting favorites
      for row in reader:
          favorite = row["language"]
          if favorite in counts:
              counts[favorite] += 1
          else:
              counts[favorite] = 1

  # Print counts
  for favorite in counts:
      print(f"{favorite}: {counts[favorite]}")
  • 请注意,当键favorite中的counts值已存在时,该值将递增。如果它不存在,我们定义counts[favorite]并将其设置为 1。此外,格式化字符串已得到改进,以显示counts[favorite]。
  • Python 还允许排序counts。按如下方式改进代码:
  # Sorts favorites by key

  import csv

  # Open CSV file
  with open("favorites.csv", "r") as file:

      # Create DictReader
      reader = csv.DictReader(file)

      # Counts
      counts = {}

      # Iterate over CSV file, counting favorites
      for row in reader:
          favorite = row["language"]
          if favorite in counts:
              counts[favorite] += 1
          else:
              counts[favorite] = 1

  # Print counts
  for favorite in sorted(counts):
      print(f"{favorite}: {counts[favorite]}")
  • 请注意代码底部的sorted(counts)。
  • 如果你查看 Python 文档中sorted函数的参数,你会发现它有许多内置参数。你可以利用其中一些内置参数,如下所示:
  # Sorts favorites by value

  import csv

  # Open CSV file
  with open("favorites.csv", "r") as file:

      # Create DictReader
      reader = csv.DictReader(file)

      # Counts
      counts = {}

      # Iterate over CSV file, counting favorites
      for row in reader:
          favorite = row["language"]
          if favorite in counts:
              counts[favorite] += 1
          else:
              counts[favorite] = 1

  def get_value(language):
      return counts[language]

  # Print counts
  for favorite in sorted(counts, key=get_value, reverse=True):
      print(f"{favorite}: {counts[favorite]}")
  • 请注意,将创建一个get_value函数,并且函数本身作为参数传递给sorted函数。key参数允许你告诉 Python 你希望用于对项目进行排序的方法。
  • Python具有我们迄今为止尚未看到的独特功能:它允许使用 匿名 或lambda函数。当你不想费心创建完全不同的函数时,可以使用这些函数。请注意以下修改:
  # Sorts favorites by value using lambda function

  import csv

  # Open CSV file
  with open("favorites.csv", "r") as file:

      # Create DictReader
      reader = csv.DictReader(file)

      # Counts
      counts = {}

      # Iterate over CSV file, counting favorites
      for row in reader:
          favorite = row["language"]
          if favorite in counts:
              counts[favorite] += 1
          else:
              counts[favorite] = 1

  # Print counts
  for favorite in sorted(counts, key=lambda language: counts[language], reverse=True):
      print(f"{favorite}: {counts[favorite]}")
  • 请注意,get_value函数已被删除。相反,lambda language: counts[language]在一行中执行我们以前的两行函数所做的工作。
  • 我们可以更改我们正在检查的列,专注于我们最喜欢的问题:
  # Favorite problem instead of favorite language

  import csv

  # Open CSV file
  with open("favorites.csv", "r") as file:

      # Create DictReader
      reader = csv.DictReader(file)

      # Counts
      counts = {}

      # Iterate over CSV file, counting favorites
      for row in reader:
          favorite = row["problem"]
          if favorite in counts:
              counts[favorite] += 1
          else:
              counts[favorite] = 1

  # Print counts
  for favorite in sorted(counts, key=lambda problem: counts[problem], reverse=True):
      print(f"{favorite}: {counts[favorite]}")
  • 请注意,problem替换了language。
  • 如果我们想允许用户直接在终端中提供输入怎么办?我们可以修改我们的代码,利用我们之前关于用户输入的知识:
  # Favorite problem instead of favorite language

  import csv

  # Open CSV file
  with open("favorites.csv", "r") as file:

      # Create DictReader
      reader = csv.DictReader(file)

      # Counts
      counts = {}

      # Iterate over CSV file, counting favorites
      for row in reader:
          favorite = row["problem"]
          if favorite in counts:
              counts[favorite] += 1
          else:
              counts[favorite] = 1

  # Print count
  favorite = input("Favorite: ")
  if favorite in counts:
      print(f"{favorite}: {counts[favorite]}")
  • 请注意,与我们在 C 语言中的经验相比,我们的代码是多么紧凑。

Relational Databases


  • Google,Twitter和Meta都使用关系数据库来大规模存储其信息。
  • 关系数据库将数据存储在称为的结构中的行和列中。
  • SQL 允许四种类型的命令:
  Create
  Read
  Update
  Delete
  • 这四种操作被亲切地称为CRUD
  • 我们可以通过键入sqlite3 favorites.db在终端上创建一个SQL数据库。出现提示后,我们将同意创建favorites.db要按y。
  • 你会注意到一个不同的提示,因为我们现在在一个名为sqlite3的程序中。
  • 我们可以通过输入.mode csv将sqlite3进入csv模式。然后,我们可以通过键入.import favorites.csv favorites从我们的csv文件中导入数据。似乎什么都没发生!
  • 我们可以键入.schema以查看数据库的结构。
  • 你可以使用语法SELECT columns FROM table从表中读取项目。
  • 例如,你可以键入SELECT * FROM favorites;``favorites将迭代 中的每一行。
  • 你可以使用命令SELECT language FROM favorites;获取数据的子集。
  • SQL 支持许多命令来访问数据,包括:
  AVG
  COUNT
  DISTINCT
  LOWER
  MAX
  MIN
  UPPER
  • 例如,你可以键入SELECT COUNT(language) FROM favorites; 。此外,你可以键入SELECT DISTINCT(language) FROM favorites;以获取数据库中各个语言的列表。你甚至可以键入SELECT COUNT(DISTINCT(language)) FROM favorites;以获取这些计数。
  # Searches database popularity of a problem

  import csv

  from cs50 import SQL

  # Open database
  db = SQL("sqlite:///favorites.db")

  # Prompt user for favorite
  favorite = input("Favorite: ")

  # Search for title
  rows = db.execute("SELECT COUNT(*) FROM favorites WHERE problem LIKE ?", "%" + favorite + "%")

  # Get first (and only) row
  row = rows[0]

  # Print popularity
  print(row["COUNT(*)"])
  • SQL 提供了我们可以在查询中使用的其他命令:
  WHERE       -- adding a Boolean expression to filter our data
  LIKE        -- filtering responses more loosely
  ORDER BY    -- ordering responses
  LIMIT       -- limiting the number of responses
  GROUP BY    -- grouping responses together
  • 请注意,我们用--在 SQL 中编写注释。
  • 例如,我们可以执行SELECT COUNT(*) FROM favorites WHERE language = 'C';。显示计数。
  • 此外,我们可以键入SELECT COUNT(*) FROM favorites WHERE language = 'C' AND problem = 'Mario';。请注意如何利用AND来缩小我们的结果范围。
  • 同样,我们可以执行SELECT language, COUNT(*) FROM favorites GROUP BY language;。这将提供一个临时表,显示语言和计数。
  • 我们可以通过键入SELECT language, COUNT(*) FROM favorites GROUP BY language ORDER BY COUNT(*);来改善这一点。这将按count对表进行排序。
  • 我们也可以使用INSERT INTO table (column...) VALUES(value, ...);往SQL数据库INSERT数据 .
  • 我们可以执行INSERT INTO favorites (language, problem) VALUES ('SQL', 'Fiftyville');。
  • 我们还可以利用UPDATE命令来更新你的数据。
  • 例如,你可以执行UPDATE favorites SET language = 'C++' WHERE language = 'C';。这将导致覆盖所有以前的语句,其中 C 是最喜欢的编程语言。
  • 请注意,这些查询具有巨大的功能。因此,在实际设置中,应考虑谁有权执行某些命令。
  • DELETE允许你删除部分数据。例如,你可以DELETE FROM favorites WHERE problem = 'Tideman';。

IMDb


  • IMDb 提供了一个包含人物、节目、作家、开始、流派和评级的数据库。其中每个表彼此相关,如下所示:
  • 下载 show.db 后,你可以在终端窗口中执行sqlite3 shows.db。
  • 执行时,.schema你不仅会找到每个表,还会找到每个字段中的各个字段。
  • 如上图所示,shows有一个id字段。该genres表有一个show_id字段,其中包含它和shows表之间的通用数据。
  • 正如你在上图中也看到的那样,show_id存在于所有表中。在shows表中,它简称为id。所有字段之间的此公共字段称为 。主键用于标识表中的唯一记录。外键 用于通过指向另一个表中的主键来构建表之间的关系。
  • 如上所述,通过将数据存储在关系数据库中,可以更有效地存储数据。
  • sqlite 中,我们有五种数据类型,包括:
  BLOB       -- binary large objects that are groups of ones and zeros
  INTEGER    -- an integer
  NUMERIC    -- for numbers that are formatted specially like dates
  REAL       -- like a float
  TEXT       -- for strings and the like
  • 此外,还可以设置列以添加特殊约束:
  NOT NULL
  UNIQUE
  • 为了进一步说明这些表之间的关系,我们可以执行以下命令:SELECT * FROM people LIMIT 10;。检查输出,我们可以执行SELECT * FROM shows LIMIT 10;。此外,我们可以执行SELECT * FROM stars LIMIT 10;。show_id是此最终查询中的外键,因为show_id对应于shows中的唯一id字段。 person_id对应于people列中的唯一字段id。
  • 我们可以进一步利用这些数据来理解这些关系。执行SELECT * FROM genres;。有很多流派!
  • 我们可以通过执行SELECT * FROM genres WHERE genre = 'Comedy' LIMIT 10;来进一步限制这些数据。从此查询中,你可以看到呈现了 10 个节目。
  • 你可以通过执行SELECT * FROM shows WHERE id = 626124;来发现这些显示的内容。
  • 我们可以通过执行以下命令进一步提高查询效率
SELECT title 
FROM shows 
WHERE id IN (
  SELECT * 
  FROM genres 
  WHERE genre = 'Comedy'
) 
LIMIT 10;
  • 请注意,此查询将两个查询嵌套在一起。内部查询由外部查询使用。
  • 我们可以通过执行进一步完善
SELECT title 
FROM shows 
WHERE id IN (
  SELECT * 
  FROM genres 
  WHERE genre = 'Comedy'
) 
ORDER BY title LIMIT 10;
  • 如果你想找到史蒂夫·卡瑞尔主演的所有节目怎么办?你可以执行SELECT * FROM people WHERE name = 'Steve Carell';。你会找到他的id。你可以利用这一id来定位他出现的许多shows。但是,一一尝试会很乏味。我们接下来如何进行查询以使其更加简化?请考虑以下事项:
  SELECT title FROM shows WHERE id IN
    (SELECT show_id FROM stars WHERE person_id =
      (SELECT * FROM people WHERE name = 'Steve Carell'));
  • 请注意,这个冗长的查询将产生一个最终结果,该结果对于发现问题的答案很有用。

JOINs


  • 请考虑以下两个表:
  • 我们如何暂时合并表格?可以使用JOIN命令将表连接在一起。
  • 执行以下命令:
  SELECT * FROM shows
    JOIN ratings on shows.id = ratings.show_id
    WHERE title = 'The Office';
  • 现在你可以看到所有被称为 The Office 节目。
  • 你可以通过执行以下JOIN命令来类似地应用于上面的史蒂夫·卡瑞尔查询:
  SELECT title FROM people
    JOIN stars ON people.id = stars.person_id
    JOIN shows ON stars.show_id = shows.id
    WHERE name = `Steve Carell`;
  • 请注意每个JOIN命令如何告诉我们哪些列与哪些其他列对齐。
  • 这可以类似地实现如下:
  SELECT title FROM people, stars, shows
  WHERE people.id = stars.person_id
  AND stars.show_id = shows.id
  AND name = 'Steve Carell';
  • 请注意,这将获得相同的结果。
  • 通配符%运算符可用于查找所有名字以Steve C开头的人都可以使用该语法SELECT * FROM people WHERE name LIKE 'Steve C%';。

Indexes


  • 虽然关系数据库能够比使用CSV文件更快、更健壮,但可以使用 索引 在表中优化数据。
  • 索引可用于加快我们的查询速度。
  • 我们可以通过在sqlite3中执行.timer on来跟踪查询速度。
  • 若要了解索引如何加快查询速度,请运行以下命令:SELECT * FROM shows WHERE title = 'The Office'; 请注意查询执行后显示的时间。
  • 然后,我们可以创建一个语法CREATE INDEX title_index on shows (title);。这告诉sqlite3创建一个索引并执行与title列相关的一些特殊的底层优化。
  • 这将创建一个名为 B树 的数据结构,该数据结构看起来类似于二叉树。但是,与二叉树不同,可以有两个以上的子节点。
  • 运行查询SELECT * FROM shows WHERE title = 'The Office';,你会注意到查询运行得更快!
  • 遗憾的是,为所有列编制索引会导致占用更多存储空间。因此,需要权衡提高速度。

Using SQL in Python


  • 为了在本课程中帮助使用 SQL,可以在代码中按如下方式使用 CS50 库:
from cs50 import SQL
  • 与以前使用 CS50 库类似,此库将帮助完成在 Python 代码中使用 SQL 的复杂步骤。
  • 你可以在文档中阅读有关 CS50 库的 SQL 功能的更多信息。
  • 回想一下我们上次在favorites.py中离开的地方。你的代码应如下所示:
  # Favorite problem instead of favorite language

  import csv

  # Open CSV file
  with open("favorites.csv", "r") as file:

      # Create DictReader
      reader = csv.DictReader(file)

      # Counts
      counts = {}

      # Iterate over CSV file, counting favorites
      for row in reader:
          favorite = row["problem"]
          if favorite in counts:
              counts[favorite] += 1
          else:
              counts[favorite] = 1

  # Print count
  favorite = input("Favorite: ")
  if favorite in counts:
      print(f"{favorite}: {counts[favorite]}")
  • 按如下方式修改代码:
  # Searches database popularity of a problem

  import csv

  from cs50 import SQL

  # Open database
  db = SQL("sqlite:///favorites.db")

  # Prompt user for favorite
  favorite = input("Favorite: ")

  # Search for title
  rows = db.execute("SELECT COUNT(*) FROM favorites WHERE problem LIKE ?", "%" + favorite + "%")

  # Get first (and only) row
  row = rows[0]

  # Print popularity
  print(row["COUNT(*)"])
         
  • 请注意,db = SQL("sqlite:///favorites.db")向 Python 提供数据库文件的位置。然后,以rows开头的行使用db.execute执行 SQL 命令。实际上,此命令将引号内的语法传递给db.execute函数。我们可以使用此语法发出任何 SQL 命令。此外,请注意,rows作为字典列表返回。在这种情况下,只有一个结果(一行)作为字典返回到行列表中。

Race Conditions


  • 使用 SQL 有时会导致一些问题。
  • 你可以想象这样一种情况:多个用户可能同时访问同一数据库并执行命令。
  • 这可能会导致代码被其他人的操作中断的故障。这可能会导致数据丢失。
  • 内置的 SQL 功能(如BEGIN TRANSACTION 、COMMIT和ROLLBACK)有助于避免其中一些争用条件问题。

SQL Injection Attacks


  • 现在,仍在考虑上面的代码,你可能想知道上面的?有什么作用。在SQL的实际应用中可能出现的问题之一是所谓的 注入攻击。注入攻击是恶意参与者可以输入恶意 SQL 代码的地方。
  • 例如,考虑登录屏幕,如下所示:
  • 如果没有我们自己的代码中的适当保护,不良行为者可能会运行恶意代码。请考虑以下事项:
   rows = db.execute("SELECT COUNT(*) FROM favorites WHERE problem LIKE ?", "%" + favorite + "%")
  • 请注意,由于?已就位,因此可以在查询盲目接受favorite验证之前运行验证。
  • 你永远不希望在上述查询中使用格式化字符串或盲目信任用户的输入。
  • 利用 CS50 库,该库将清理并删除任何潜在的恶意字符。

Summing Up


在本课中,你学习了更多与 Python 相关的语法。此外,你还学习了如何将这些知识与平面文件和关系数据库形式的数据集成。最后,你了解了 SQL。具体来说,我们讨论了...

  • 平面文件数据库
  • 关系数据库
  • SQL
  • JOINs
  • 索引
  • 在 Python 中使用 SQL
  • 竞争条件
  • SQL 注入攻击

下次见!


原文出处:https://cs50.harvard.edu/college/2022/fall/notes/7/

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码