목차
Ruby操作MySQL
连接mysql
query()查询和结果处理
查询选项含义以及默认查询选项
prepare()+execute()
处理多结果集
Mysql2的EventMachine
ORM之:Sequel
데이터 베이스 MySQL 튜토리얼 Ruby는 MySQL을 작동하기 위해 Mysql2 연결을 어떻게 사용합니까?

Ruby는 MySQL을 작동하기 위해 Mysql2 연결을 어떻게 사용합니까?

Apr 17, 2023 pm 10:07 PM
mysql ruby

Ruby操作MySQL

使用mysql2连接mysql并操作mysql。

gem install mysql2
로그인 후 복사

连接mysql

建立连接:

require 'mysql2'

conn = Mysql2::Client.new({ 
  host: '192.168.200.73',
  username: 'root',
  password: 'P@ssword1!'
})
로그인 후 복사

接受的连接选项包括:

Mysql2::Client.new(
  :host,
  :username,
  :password,
  :port,
  :database,
  :socket = '/path/to/mysql.sock',
  :flags = REMEMBER_OPTIONS | LONG_PASSWORD | LONG_FLAG | TRANSACTIONS | PROTOCOL_41 | SECURE_CONNECTION | MULTI_STATEMENTS,
  :encoding = 'utf8',
  :read_timeout = seconds,
  :write_timeout = seconds,
  :connect_timeout = seconds,
  :connect_attrs = {:program_name => $PROGRAM_NAME, ...},
  :reconnect = true/false,
  :local_infile = true/false,
  :secure_auth = true/false,
  :ssl_mode = :disabled / :preferred / :required / :verify_ca / :verify_identity,
  :default_file = '$HOME/.my.cnf',   #=> 从文件读取连接信息
  :default_group = 'my.cfg section', #=> 选择.my.cnf中的section
  :default_auth = 'authentication_windows_client',
  :init_command => SQL_Statement  #=>主要用于设置本次连接时的某些变量
)
로그인 후 복사

连接建立后就可以操作数据库了,比如执行SQL语句:

conn. query('create databse mytest')
conn.select_ db( 'mytest' )
# conn.query('use mytest' )
conn. query('create table tb(name varchar(1024),age int)')
conn. query <<-SQL
    insert into tb values 
    (&#39;junmajinlong&#39;, 23), 
    ( &#39;woniu&#39;, 25),
    (&#39;fairy&#39;, 26)
SQL
로그인 후 복사

如果测试和mysql的连接是否断开,可执行ping():

conn.ping
로그인 후 복사

如果连接未断开,ping()返回true,如果连接已断开但已启用auto-reconnect,则ping()会尝试依次reconnect,连接成功则返回true,否则报错。如果连接已断开,且未启用auto-reconnect,则报错。

query()查询和结果处理

query()用于执行任何允许的SQL语句,比如执行查询语句。

查询结果可使用each进行迭代,迭代时传递查询到的每一行记录,可使用hash索引的方式(默认以hash类型保存每一行)查询某个字段的内容:

conn.query("show databases").each do |row| pp row end
=begin
{"Database"=>"information_schema"}
{"Database"=>"mysql"}
{"Database"=>"mytest"}
{"Database"=>"performance_schema"}
{"Database"=>"sys"}
=end

conn.query("select * from mytest.tb").each do |row|
  pp row
  pp row["name"]
end
=begin
{"name"=>"junmajinlong", "age"=>23}
"junmajinlong"
{"name"=>"woniu", "age"=>25}
"woniu"
{"name"=>"fairy", "age"=>26}
"fairy"
=end
로그인 후 복사

可见,查询结果中,每一行数据默认以hash格式保存。

实际上,对于增删改的SQL语句,query()的返回值为nil,对于查询类的语句,其返回值以Mysql2::Result对象返回

conn.query("create table mytest.t1(id int)")
#=> nil
res = conn.query("select * from mytest.tb")
p res
로그인 후 복사

结果:

#<Mysql2::Result:0x00007fffe833a230
 @query_options=
  {:as=>:hash,
   :async=>false,
   :cast_booleans=>false,
   :symbolize_keys=>false,
   :database_timezone=>:local,
   :application_timezone=>nil,
   :cache_rows=>true,
   :connect_flags=>2148540933,
   :cast=>true,
   :default_file=>nil,
   :default_group=>nil,
   :host=>"192.168.200.73",
   :username=>"root",
   :password=>"P@ssword1!"},
 @server_flags=
   {:no_good_index_used=>false, 
     :no_index_used=>true, 
     :query_was_slow=>false}>
로그인 후 복사

query()各查询选项的含义以及默认的查询选项参见下文。先了解两个:

  • :as项表示以数组方式(:as=>:array)还是hash方式(:as=>:hash)存储查询结果

  • :symbolize_keys表示返回hash结果时,其key是否设置为符号类型,默认为false,即key是字符串类型

可在查询时指定这些参数,也可在each迭代时指定这些参数,例如:

conn.query("select * from mytest.tb", symbolize_keys: true).each do |row|
  pp row
end

conn.query("select * from mytest.tb").each(symbolize_keys: true) do |row|
  pp row
end
로그인 후 복사

结果:

{:name=>"junmajinlong", :age=>23}
{:name=>"woniu", :age=>25}
{:name=>"fairy", :age=>26}
로그인 후 복사

虽然大多数时候使用hash保存每一行数据更方便,但有时候也会想要以数组方式操作每一行数据,例如连接每一个字段的值:

sql = &#39;select * from mytest.tb&#39;
res = conn.query(sql)
res.each(as: :array) do |row|
  p row.join(",")
end
로그인 후 복사

结果:

"junmajinlong,23"
"woniu,25"
"fairy,26"
로그인 후 복사

Mysql2::Result自身具备的方法不多:

#count ⇒ Object (also: #size)
#each(*args) ⇒ Object
#fields ⇒ Object
#free ⇒ Object
로그인 후 복사

外,Mysql2::Result已经mix-in了Enumerable模块,所以可直接使用该模块中的方法,例如first表示取第一行记录。

sql = &#39;select * from mytest.tb&#39;
res = conn.query(sql)
res.first
#=>{"name"=>"junmajinlong", "age"=>23}
로그인 후 복사

需注意,所有SQL语句中涉及到的值都是未经转义的,有时候需要也建议在执行它们之前先对它们进行转义。

escaped = conn.escape("gi&#39;thu\"bbe\0r&#39;s")
results = conn.query("SELECT * FROM users WHERE group=&#39;#{escaped}&#39;")
로그인 후 복사

查询选项含义以及默认查询选项

query()默认的查询选项可以通过Mysql2::Client.default_query_options获取,它是一个hash结果:

Mysql2::Client.default_query_options
=begin
{:as=>:hash,
 :async=>false,
 :cast_booleans=>false,
 :symbolize_keys=>false,
 :database_timezone=>:local,
 :application_timezone=>nil,
 :cache_rows=>true,
 :connect_flags=>2148540933,
 :cast=>true,
 :default_file=>nil,
 :default_group=>nil}
=end
로그인 후 복사

其中(重要):

  • :as项表示以数组方式(:as=>:array)还是hash方式(:as=>:hash)存储查询结果

  • :symbolize_keys表示返回hash结果时,其key是否设置为符号类型,默认为false,即key是字符串类型

  • :async表示查询是否异步模式,即是否非阻塞的查询,参考https://github.com/brianmario/mysql2#async

  • :cast指示MySQL的查询结果转换为Ruby数据时是否进行类型转换,如果确定本次查询的字段类型和Ruby的类型完全对应,可禁用casting功能提升效率

  • :database_timezone指示Ruby接收MySQL返回的日期时间数据时的时区,mysql2将先以该时区创建日期时间对象来保存对应字段的值。仅支持:local:utc两个值

  • :application_timezone指示最终Mysql2::Result中的日期时间的时区,即程序端的时区。因此,mysql2先以”无损”的时区从MySQL获取日期时间数据,并根据application_timezone将其转换成程序端时区的日期时间对象

  • :cache_rows指示是否缓存构建出来的hash行或array行

  • Mysql2处理查询结果的流程:

    • Mysql2的MySQL C api从MySQL服务端查询数据,并保存在Ruby的查询结果集(结果集属于C)

    • Mysql2::Result和C端结果集是关联的,当释放Mysql2::Result,也会对C结果集进行GC

    • Mysql2在需要取得结果集中的数据时(比如each迭代),才从结果集中根据查询选项构建所需行并返回,比如构建hash结构的行,构建数组结构的行,构建hash结构时将key转换为Symbol类型等

    • 默认情况下,从结果集中查询并构建出来的hash行或array行会缓存在Ruby中,使得下次再次请求这一行时(比如再次迭代),可用直接从缓存中取得hash行或array行

    • 比如从MySQL服务端查询了100行数据保存在C的结果集中,第一次以hash方式请求其中4行,这4行hash数据会缓存起来,如果下次再从头开始以hash方式请求15行,则前4行来自于缓存,后11行来自于结果集的临时构建

    • 如果:cache_rows未禁用,当结果集中的所有行都被缓存,Mysql2::Result将会去释放C端的结果集

    • 如果能确保查询的结果集只使用一次,可禁用:cache_rows,这会提升效率

  • :stream: true表示以Stream的方式处理查询结果。有时候查询结果数据量非常大,Ruby端不方便存放所有结果,可采用stream的方式去处理本次查询:一边从MySQL服务端取数据放进结果集,一边从结果集中取数据进行处理(比如迭代)。使用stream时,会自动关闭cache_rows,因为它们是互相冲突的概念。此外,使用stream模式要求必须迭代完所有数据集才会执行下一条查询,因为一个mysql连接在某一时刻只能执行一个操作,在迭代完之前,本次查询操作还尚未完成。

修改Mysql2::Client.default_query_options可以设置默认query()的查询选项。如果想要设置其中某选项,可以通过hash合并的方式来设置该选项。

Mysql2::Client.default_query_options
#=> {:as=>:hash, ...}

Mysql2::Client.default_query_options.merge!(:as => :array)
#=> {:as=>:array, ...}
로그인 후 복사

prepare()+execute()

除了直接使用query()执行SQL语句查询数据库,也可以使用prepare()方法将字符串准备成一个待执行的SQL语句,其中可以使用?充当占位符。

prepare后的语句是一个Mysql2::Statement对象,该对象有一个execute()方法,可以用来执行这个准备好的语句,它可指定查询选项,且其返回值同query()一样:对于增删改操作,返回值为nil,对于查询类操作,返回Mysql2::Result结果对象。

res_sql = conn.prepare(&#39;select * from mytest.tb where age >= ? and name like ?&#39;)
res = res_sql.execute(20, &#39;%junma%&#39;, as: :array)
res.first
로그인 후 복사

处理多结果集

有些存储过程中可能包含多个查询结果集,或者有时候会在一行SQL中包含多个select语句而同时返回多个结果集,Mysql2能很好地处理多结果集问题。

要处理多结果集,连接mysql时必须指定一个flag:

conn = Mysql2::Client.new({
  host: "192.168.200.73",
  username: "root",
  password: "P@ssword1!",
  flags: Mysql2::Client::MULTI_STATEMENTS
})
로그인 후 복사

然后执行多结果集的多个查询语句:

res = conn.query(&#39;select 1;select 2;select 3&#39;)
로그인 후 복사

虽然本次query()涉及了多个select语句,Mysql2也已经保存了这三个select的查询结果集(保存在结果集队列中),但本次query()方法的返回值仅是第一个结果集,所以res中保存的是第一个结果集的内容。

res.first   #=> {"1"=>1}
로그인 후 복사

要获取剩余的结果集,可通过conn.next_result将结果集偏移指针移到下一个结果集,然后通过conn.store_result获取下一个结果集,依次类推,直到没有剩余结果集后,conn.next_result返回false。可通过more_results?()方法判断是否还有剩余的结果集。

conn.next_result
res = conn.store_result
res.first #=> {"2"=>2}

conn.next_result
res = conn.store_result
res.first #=> {"3"=>3}

conn.next_result  #=> false
로그인 후 복사

所以,可遍历多个结果集:

res = conn.query(&#39;select 1;select 2;select 3&#39;)
loop do
  p res.first
  break unless conn.next_result
  res = conn.store_result
end

# 或者
p res.first
while conn.next_result
  res = conn.store_result
  p res.first
end
로그인 후 복사

输出结果:

{"1"=>1}
{"2"=>2}
{"3"=>3}
로그인 후 복사

需注意,开启多行语句(即多结果集)功能后,所查询得到的所有结果集必须已经处理完成(严格来说,是存放结果集的队列已经为空),才能继续执行后续的SQL语句(事实上,经测试,结果集队列未空的情况下执行其它SQL语句会导致直接断开mysql连接)。可使用abandon_results!()方法强行丢弃所有剩余结果集,使得Mysql2马上回归正常状态:可向MySQL服务端发送SQL语句。

# res和res1都只保存第一个结果集
# 但结果集队列中保留的是select 5和select 6的结果集
res = conn.query(&#39;select 1;select 2;select 3&#39;)
conn.abandon_results!  # 丢弃所有剩余结果集
res1 = conn.query('select 4;select 5;select 6')
로그인 후 복사

另外,如果多个查询语句中间的某个查询语句报错,它将影响其后面的语句不会执行,所以无法获取后面的结果集。

res = conn.query(&#39;select 1;select 2;select A;select 3&#39;)
loop do
  p res.first
  break unless conn.next_result
  res = conn.store_result
end
로그인 후 복사

结果:

{"1"=>1}
{"2"=>2}
Mysql2::Error: Unknown column &#39;A&#39; in &#39;field list&#39;
로그인 후 복사

Mysql2的EventMachine

Mysql2支持EM,可以执行异步的query(),此外,可以指定当query()查询成功或失败时的回调语句块:

require &#39;mysql2/em&#39;

EM.run do
  client1 = Mysql2::EM::Client.new
  defer1 = client1.query "SELECT sleep(3) as first_query"
  defer1.callback do |result|
    puts "Result: #{result.to_a.inspect}"
  end

  client2 = Mysql2::EM::Client.new
  defer2 = client2.query "SELECT sleep(1) second_query"
  defer2.callback do |result|
    puts "Result: #{result.to_a.inspect}"
  end
end
로그인 후 복사

ORM之:Sequel

Active:Record应该是最为人熟知的orm,其功能极其丰富。

另一个轻量级的ORM是Sequel,它支持ADO, JDBC, MySQL, Mysql2, ODBC, Oracle, PostgreSQL, SQLite3等等。

例如:

require &#39;sequel&#39;

# 创建数据库实例
DB = Sequel.connect(
  adapter: :mysql2,
  user: &#39;root&#39;,
  password: &#39;P@ssword1!&#39;,
  host: &#39;192.168.200.73&#39;,
  port: 3306,
  database: &#39;mytest&#39;
)

# 创建数据集,数据集表示的是一张表或表部分数据
# 此时不会去查询数据,会推迟到需要数据时才查询
dataset = DB[:tb]

# 迭代表数据
dataset.each do |row|
  pp row
end

# 条件查询
pp dataset.where(name: &#39;junmajinlong&#39;, age: 23).first
pp dataset.where { name =~ "junmajinlong" and age =~ 23 }.first
로그인 후 복사

위 내용은 Ruby는 MySQL을 작동하기 위해 Mysql2 연결을 어떻게 사용합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

MySQL : 초보자를위한 데이터 관리의 용이성 MySQL : 초보자를위한 데이터 관리의 용이성 Apr 09, 2025 am 12:07 AM

MySQL은 설치가 간단하고 강력하며 데이터를 쉽게 관리하기 쉽기 때문에 초보자에게 적합합니다. 1. 다양한 운영 체제에 적합한 간단한 설치 및 구성. 2. 데이터베이스 및 테이블 작성, 삽입, 쿼리, 업데이트 및 삭제와 같은 기본 작업을 지원합니다. 3. 조인 작업 및 하위 쿼리와 같은 고급 기능을 제공합니다. 4. 인덱싱, 쿼리 최적화 및 테이블 파티셔닝을 통해 성능을 향상시킬 수 있습니다. 5. 데이터 보안 및 일관성을 보장하기위한 지원 백업, 복구 및 보안 조치.

Navicat에서 데이터베이스 비밀번호를 검색 할 수 있습니까? Navicat에서 데이터베이스 비밀번호를 검색 할 수 있습니까? Apr 08, 2025 pm 09:51 PM

Navicat 자체는 데이터베이스 비밀번호를 저장하지 않으며 암호화 된 암호 만 검색 할 수 있습니다. 솔루션 : 1. 비밀번호 관리자를 확인하십시오. 2. Navicat의 "비밀번호 기억"기능을 확인하십시오. 3. 데이터베이스 비밀번호를 재설정합니다. 4. 데이터베이스 관리자에게 문의하십시오.

Navicat Premium을 만드는 방법 Navicat Premium을 만드는 방법 Apr 09, 2025 am 07:09 AM

Navicat Premium을 사용하여 데이터베이스 생성 : 데이터베이스 서버에 연결하고 연결 매개 변수를 입력하십시오. 서버를 마우스 오른쪽 버튼으로 클릭하고 데이터베이스 생성을 선택하십시오. 새 데이터베이스의 이름과 지정된 문자 세트 및 Collation의 이름을 입력하십시오. 새 데이터베이스에 연결하고 객체 브라우저에서 테이블을 만듭니다. 테이블을 마우스 오른쪽 버튼으로 클릭하고 데이터 삽입을 선택하여 데이터를 삽입하십시오.

MySQL에서 테이블을 복사하는 방법 MySQL에서 테이블을 복사하는 방법 Apr 08, 2025 pm 07:24 PM

MySQL에서 테이블을 복사하려면 새 테이블을 만들고, 데이터를 삽입하고, 외래 키 설정, 인덱스 복사, 트리거, 저장된 절차 및 기능이 필요합니다. 특정 단계에는 다음이 포함됩니다 : 동일한 구조를 가진 새 테이블 작성. 원래 테이블의 데이터를 새 테이블에 삽입하십시오. 동일한 외래 키 제약 조건을 설정하십시오 (원래 테이블에 하나가있는 경우). 동일한 색인을 만듭니다. 동일한 트리거를 만듭니다 (원래 테이블에 하나가있는 경우). 동일한 저장된 절차 또는 기능을 만듭니다 (원래 테이블이 사용되는 경우).

MariaDB 용 Navicat에서 데이터베이스 비밀번호를 보는 방법은 무엇입니까? MariaDB 용 Navicat에서 데이터베이스 비밀번호를 보는 방법은 무엇입니까? Apr 08, 2025 pm 09:18 PM

MariaDB 용 Navicat은 암호가 암호화 된 양식으로 저장되므로 데이터베이스 비밀번호를 직접 볼 수 없습니다. 데이터베이스 보안을 보장하려면 비밀번호를 재설정하는 세 가지 방법이 있습니다. Navicat을 통해 비밀번호를 재설정하고 복잡한 비밀번호를 설정하십시오. 구성 파일을 봅니다 (권장되지 않음, 위험이 높음). 시스템 명령 줄 도구를 사용하십시오 (권장되지 않으면 명령 줄 도구에 능숙해야 함).

Navicat에서 SQL을 실행하는 방법 Navicat에서 SQL을 실행하는 방법 Apr 08, 2025 pm 11:42 PM

Navicat에서 SQL을 수행하는 단계 : 데이터베이스에 연결하십시오. SQL 편집기 창을 만듭니다. SQL 쿼리 또는 스크립트를 작성하십시오. 실행 버튼을 클릭하여 쿼리 또는 스크립트를 실행하십시오. 결과를 봅니다 (쿼리가 실행 된 경우).

Navicat에서 MySQL에 새로운 연결을 만드는 방법 Navicat에서 MySQL에 새로운 연결을 만드는 방법 Apr 09, 2025 am 07:21 AM

응용 프로그램을 열고 새로운 연결 (Ctrl n)을 선택하여 Navicat에서 새로운 MySQL 연결을 만들 수 있습니다. "MySQL"을 연결 유형으로 선택하십시오. 호스트 이름/IP 주소, 포트, 사용자 이름 및 비밀번호를 입력하십시오. (선택 사항) 고급 옵션을 구성합니다. 연결을 저장하고 연결 이름을 입력하십시오.

Navicat은 mysql/mariadb/postgresql 및 기타 데이터베이스에 연결할 수 없습니다 Navicat은 mysql/mariadb/postgresql 및 기타 데이터베이스에 연결할 수 없습니다 Apr 08, 2025 pm 11:00 PM

Navicat이 데이터베이스 및 해당 솔루션에 연결할 수없는 일반적인 이유 : 1. 서버의 실행 상태를 확인하십시오. 2. 연결 정보를 확인하십시오. 3. 방화벽 설정을 조정하십시오. 4. 원격 액세스 구성; 5. 네트워크 문제 문제 해결; 6. 권한을 확인하십시오. 7. 버전 호환성을 보장합니다. 8. 다른 가능성 문제를 해결하십시오.

See all articles