20201018のMySQLに関する記事は6件です。

MySQLでもできる! 全文検索のやり方と条件検索!

はじめに

MySQLで、全文検索ができるって知ってましたか?
今回はMySQLでの全文検索のやり方について簡単に紹介していきます!!

【YouTube動画】 MySQL 全文検索 高度な検索のやり方
MySQL 全文検索 高度な検索のやり方

MySQLの全文検索

全文検索とは、複数の文章群から特定の文字列を検索することです。
全文検索として、grep型とindex型があります。

grep型は実行時に中身を走査する方式で、検索対象が大きくなると、速度が低下します。
MySQLでいうとLINKE句を使って、文字列を検索することに相当します。

index型はDB登録時にIndexを作成する方式で、メモリ消費が多い代わりに、高速に検索できます。
MySQLで使用する場合は、MATCH句やAGAINST句を使って、検索します。

全文検索の実行方法

以下のようにして、全文検索用のインデックスを作成できます。

CREATE FULLTEXT INDEX idx on articles(body);

実行するときは、MATCHで検索対象のカラムを決め、AGAINSTで条件を決めます。

SELECT id, title, body FROM articles WHERE MATCH(body) AGAINST ('TEST HOGE')

検索モード

AGAINST内で検索モードを指定することができます。
デフォルトでは、Natural Language Modeになります。

  • Natural Language Mode

デフォルトで適用されるモードで、OR検索のみを実行します。
ただ、完全一致ではないため、以下のような文字もヒットします。

「ありがとう」で検索 -> 「ありがとう」だけでなく、「あり」も検索される
  • Boolean Mode

AND, NOT, グルーピングなど高度な検索が可能になります。
実行時は以下のように指定します。

SELECT id, title, body FROM articles WHERE MATCH(body) AGAINST ('TEST +HOGE' IN BOOLEAN MODE)
  • Natural Language Mode with Query Expansion

1度 Natural Language Modeと同じように検索します。
1度目の結果で、該当する文字周辺にあった文字も記録します。
そして、周辺にあった文字も含めて検索し直すことで、関連語を表示したり、スペルミスを修正することができます。
ただ曖昧検索ができる反面、2度実行するので、結果表示が遅くなります。

演算子について (Boolean Mode)

Boolean Modeで使用できる演算子について詳しくみていきます。

何も演算子を付けない場合、OR検索になります。

AGAINST ('TEST HOGE' IN BOOLEAN MODE)

+を付けると、AND検索ができるようになります。

AGAINST ('+TEST +HOGE' IN BOOLEAN MODE)

NOT検索は-ででき、グルーピングは()で括ります。

AGAINST ('(TEST HOGE) -TE' IN BOOLEAN MODE)

完全一致をするには、""で括る必要があります。

AGAINST ('"HOGE"' IN BOOLEAN MODE)

まとめ

今回はMySQLの全文検索について紹介しました。
使い所は悩みますが、意外と簡単にできます!

MySQL編は一旦ここで終わりですが、他に何か紹介して欲しいことがあれば、ご連絡お願いします!

twitteryoutubeでのコメントもお待ちしています!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Visual Studio Code 上で MySQL を操作するための便利な拡張機能

この記事について

この記事では、Visual Studio Code 上で、以下のデータベースに接続して値を確認する方法について解説します。

  • MySQL
  • Azure SQL Database for MySQL

従来の開発では、MySQL Workbenchなど、コーディングを行う場所とは異なるアプリケーションを並行で起動する事例も多かったと思います。
コーディング中にデータベースにアクセスしたくなり別のアプリを起動・切り替えというようなことは正直面倒で無駄の時間につながります。
Visual Studio Code のみで、コーディングだけでなく、データベースの値も確認できることは、開発中に複数のアプリケーションを起動・行き来しなければならないというような、ちょっとした面倒を軽減させることが可能です。

Visual Studio Code 拡張機能

今回利用する拡張機能は、こちらです。

スクリーンショット 2020-10-17 17.37.19.png

こちらの拡張機能は Jun Han さんという方が個人で開発されているもののようです。Jun Han さんは、GitHub リポジトリを見るに、Microsoft 社の社員さんのようですね。
※残念ながら、Oracle 社や Microsoft 社など、公式のものはありませんでした。

※ちなみに、こちらの拡張機能のライセンス形態がMITライセンスとなっており、MySQL の GPL v2 ライセンスに違反している可能性があります。
また、こちらの拡張機能については、2019 年 4 月 3 日から更新が行われていないようです。(2020/10/17 現在)

Azure SQL Database for MySQL に接続

拡張機能の表示

拡張機能をインストールすると、Visual Studio Code のエクスプローラータブの中に MySQL の表示が追加されます。
タブには新しく項目が追加されません。こちら、勘違いしやすいポイントですので、ご注意ください。

スクリーンショット 2020-10-18 5.09.54.png

もし、エクスプローラータブ内に表示がされていない場合は、エクスプローラーの表示項目を確認してください。

スクリーンショット 2020-10-18 5.12.04.png

表示する項目で、MySQL がチェック ON になっていることを確認します。

SSL ルート証明書のダウンロード

Azure SQL Database for MySQL では、構築時にデフォルトで SSL 接続が強要されるようになっています。
そのため、接続に使用する SSL 証明書をダウンロードします。

SSL ルート証明書のダウンロードは、以下の Microsoft Docs を参照してください。

サーバーファイアウォールの設定

SQL Database にはサーバー ファイアウォールの設定があります。
ここで、自身の端末のクライアント IPからの接続を許可しておく必要があります。
設定していない場合は、事前に設定しておきます。

スクリーンショット 2020-10-18 13.45.40.png

接続プロファイルの作成

エクスプローラーの MYSQL 欄の横にある、+ ボタンを選択します。

スクリーンショット 2020-10-18 5.11.31.png

あるいは、[Ctrl] + [Shift] + [P](macOS の場合は [Command] + [Shift] + [P]) でコマンドパレットを表示し、MySQL: Add Connection を選択することでも対応可能です。

スクリーンショット 2020-10-18 12.11.14.png

接続先の MySQL サーバー名を入力します。

スクリーンショット 2020-10-18 13.18.24.png

ログインに使用するユーザー名を入力します。

スクリーンショット 2020-10-18 13.19.20.png

ログインに使用するユーザー名のパスワードを入力します。

スクリーンショット 2020-10-18 13.19.33.png

MySQL へ接続するためのポート番号を入力します。

スクリーンショット 2020-10-18 13.19.54.png

SSL 証明書のパスの入力を求められます。
SSL ルート証明書のダウンロードで予めダウンロードしておいた、BaltimoreCyberTrustRoot.crt.pemファイルのパスを入力します。
※画像は macOS で、ダウンロードフォルダに該当ファイルをダウンロードした場合の例

スクリーンショット 2020-10-18 13.49.53.png

値の入力が正常に完了したら、エクスプローラーの MYSQL 欄に新しく接続情報が追加され、以下のように接続ができるようになるはずです。

スクリーンショット 2020-10-18 13.53.51.png

なお、接続先の Azure SQL Database for MySQL のサーバー、およびサーバー管理者ログイン名については、Azure ポータル上で確認可能です。

スクリーンショット 2020-10-18 13.13.04.png

クエリ実行

使用するベータベースを選択し、右クリックで New Query を選択します。

スクリーンショット 2020-10-18 13.54.58.png

SQL タブが表示されるので、クエリを作成していきます。
なお、現在接続している MySQL サーバー、およびデータベースについては、Visual Studio Code 画面下部から確認できます。

スクリーンショット 2020-10-18 13.56.40.png

クエリを作成したら、画面を右クリック -> Run MySQL Queryまたは[Ctrl] + [Alt] + [E] (macOS の場合は、[Command] + [option] + [E])でクエリを実行します。

スクリーンショット 2020-10-18 14.01.35.png

実行結果は別タブで表示されます。

スクリーンショット 2020-10-18 14.03.41.png

SELECT をはじめ、さまざまなクエリを実行できるため、プログラム側で実行するクエリの実行結果を、同じ Visual Studio Code (しかもタブ移動せずに) 簡単に確認することができます。


  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SpringBoot+MyBatis+MySQLの初歩

概要

これまでJdbcTemplateの使用経験しかなくMyBatisを使ったことがなかったので、SpringBoot + MyBatis + MySQLを使用してみた。

環境

  • macOS Catalina 10.15.7
  • Java11
  • SpringBoot 2.3.4
  • MySQL 8.0
  • Gradle

やってみたこと

今回は本の情報がDBに登録されており、それを1件取得、全件表示することにします。

  • データベースからID検索し表示
  • 全件取得して一覧表示

■初回アクセス時の画面
初期画面.png

■1件検索(idをフォームに入力して検索を押下)
検索結果.png

■全件表示(一覧表示を押下)
一覧表示.png

準備する各種クラス・設定ファイルたち

  • build.gradle(こちらの依存関係にMyBatisを追加)
  • DB関連:data.sql、schema.sql
  • BookFormクラス(入力フォームからの値を受け取る)
  • ビュー画面(Thymeleaf使用)
  • Bookクラス(DBからの値を受け取るEntityクラス)
  • BookDaoインタフェース(DBへ問合せを行うためのインタフェース)
    • BookDao.xml(ここにSQLを記載。)
  • BookServiceクラス(Daoクラスを呼び出す。)
  • BookControllerクラス(ブラウザからのリクエストに応じたビューを返す。状況に応じてserviceクラスを呼び出す。)

なぜか、BookDaoはインタフェースを実装せずともBookServiceクラスから利用できる。裏側でごにょごにょ実装されてServiceクラスから利用できるようになっているらしい。

ディレクトリ構成

  • MyBatisはマッピングファイル(XMLファイル)にSQLを書くやり方を採用(アノテーション内にSQLを書くやり方もあり)。マッピングファイルはresorces配下のDaoと同じ階層に配置することで、Dao利用時に自動で読み込んでくれる。
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── example
    │   │           └── demo
    │   │               ├── ServletInitializer.java
    │   │               ├── SpringTestApplication.java
    │   │               ├── controller
    │   │               │   └── BookController.java
    │   │               ├── dao
    │   │               │   └── BookDao.java
    │   │               ├── entity
    │   │               │   └── Book.java
    │   │               ├── form
    │   │               │   └── BookForm.java
    │   │               └── service
    │   │                   └── BookService.java
    │   └── resources
    │       ├── application.properties
    │       ├── com
    │       │   └── example
    │       │       └── demo
    │       │           └── dao
    │       │               └── BookDao.xml
    │       ├── data.sql
    │       ├── schema.sql
    │       ├── static
    │       │   └── css
    │       │       └── style.css
    │       └── templates
    │           └── index.html
    └── test

依存関係

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.3'
    compileOnly 'org.projectlombok:lombok'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    runtimeOnly 'mysql:mysql-connector-java'
    annotationProcessor 'org.projectlombok:lombok'
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }

DBの定義

まずはMySQLでデータベースを作っておく。今回の例でいうとlibrary。

CREATE DATABASE library;

下記ファイルを用意すると、SpringBoot起動の度にテストデータを用意してくれる。

schema.sql
--booktableがあれば削除
DROP TABLE IF EXISTS booktable;

--booktableがなければ新しく作成
CREATE TABLE IF NOT EXISTS booktable(
id INT AUTO_INCREMENT,
book_name VARCHAR(50) NOT NULL,
volume_num INT NOT NULL,
author_name VARCHAR(50) NOT NULL,
published_date DATE NOT NULL,
PRIMARY KEY(id)
);
data.sql
--本のリスト初期データ
--idカラムはオートインクリメントなので不要
INSERT INTO booktable
(book_name, volume_num,author_name,published_date)
VALUES
( 'HUNTER X HUNTER',36,'冨樫義博','2018-10-04'),
( 'ベルセルク',40,'三浦健太郎','2018-09-28'),
( 'ドリフターズ',6,'平野耕太','2018-11-30'),
( '羅生門',1,'芥川龍之介','1915-11-01')
;

設定ファイル(application.properties)

接続先に?serverTimezone=JSTをつけないと上手くいかない。また、mybatis.configuration.map-underscore-to-camel-case=trueにより、DBのカラム名がスネークケースであってもJava側ではキャメルケースとして認識してくれる。

### データベース接続設定
spring.datasource.url=jdbc:mysql://localhost:3306/library?serverTimezone=JST
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
### スネークケースのDBカラム名をSpringのEntity側ではキャメルケースとして対応付けてくれる。
mybatis.configuration.map-underscore-to-camel-case=true
### 初期化を行うかの指定。
spring.datasource.initialization-mode=always

各種クラス

Formクラス

今回は画面からはidのみ受け取るのでフィールドは1個。HTML側のinputタグ内name属性とフィールド名は一致させておく。lombokの機能により、@Dataでセッターゲッターは追記不要。フィールドの型はプリミティブ型のintではなく、参照型(ラッパークラス)のIntegerにするのが良いらしい。ゼロとnullで区別がつくため。

BookForm.java
package com.example.demo.form;
import lombok.Data;

@Data
public class BookForm {
    private Integer id;
}

Entityクラス

データベースから取得したデータをいったん格納するオブジェクト。Formクラスにも書いたが、型は参照型が良い。

Book.java
package com.example.demo.entity;
import java.time.LocalDate;
import lombok.Data;

@Data
public class Book {
    private Integer id;
    private String bookName;
    private Integer volumeNum;
    private String authorName;
    private LocalDate publishedDate;
}

Daoインタフェースとマッピングファイル

MyBatisの場合は、インタフェースをつくり@MapperアノテーションをつけることでRepositoryクラスになる。1件検索のメソッドでは、単純に数値だけ渡すよりも、Entityクラス(Bookクラス)を介した方が、マッピングファイルの中で、Entityクラスの各フィールドを柔軟に参照できる。

BookDao
package com.example.demo.dao;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import com.example.demo.entity.Book;

@Mapper
public interface BookDao {
    //1件検索
    Book findById(Book book);

    //全件取得
    List<Book> findAll();
}

【XMLファイルについて】

  • ファイル名は対応するDaoと同じにする。
  • 配置場所はresorces配下のDaoインタフェースと同じ階層にする。
  • namespace属性にはDaoインタフェースの完全修飾クラス名を書く。
  • select要素にSELECT文を書く。
    • id属性にはDaoインタフェースの対応するメソッド名を書く。
    • resultType属性には検索結果をマッピングするクラス名を書く。今回はBookクラス。
    • parameterType属性は今回省略。メソッドの引数の型を書くらしい。省略すると、自動で実際の引数の型が判定される。
  • 下記findByIdでは、WHERE句でEntityクラス(Bookクラス)のidフィールドを参照している。
BookDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.dao.BookDao">
    <select id="findById" resultType="com.example.demo.entity.Book">
        SELECT
            id,
            book_name,
            volume_num,
            author_name,
            published_date
         FROM
            booktable
         WHERE
            id = #{id}
    </select>
    <select id="findAll" resultType="com.example.demo.entity.Book">
        SELECT
            id,
            book_name,
            volume_num,
            author_name,
            published_date
         FROM
            booktable
    </select>
</mapper>

Serviceクラス

Daoクラスでも書いたが、1件検索メソッドではEntityクラスのidフィールドに値をセットしている。全件取得はEntityクラスを要素にもつリストを返す。

package com.example.demo.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.demo.dao.BookDao;
import com.example.demo.entity.Book;

@Service
public class BookService {

    @Autowired
    BookDao bookDao;

    //1件検索
    public Book findById(Integer id) {
        Book book = new Book();
        book.setId(id);
        return this.bookDao.findById(book);
    }

    //全件取得
    public List<Book> getBookList(){
        return this.bookDao.findAll();
    }
}

Controllerクラス

下記では@GetMapping@PostMappingを使いわけてません。

BookController.java
package com.example.demo.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import com.example.demo.entity.Book;
import com.example.demo.form.BookForm;
import com.example.demo.service.BookService;

@Controller
@RequestMapping("/book")
public class BookController {

    @Autowired
    BookService bookService;

    @RequestMapping("/search")
    public String index(BookForm bookForm, String showList, Model model) {

        //タイトル
        model.addAttribute("title", "本屋さん");

        //bookform(formクラス)がnullじゃなかったら1件検索
        if(bookForm.getId() != null) {
            Book book = bookService.findById(bookForm.getId());
            model.addAttribute("book", book);
        }

        //一覧表示ボタンが押されると本一覧をmodelに登録。
        if(showList != null) {
            List<Book> bookList = bookService.getBookList();
            model.addAttribute("bookList", bookList);
        }

        return "index";

    }

}

画面

th:ifでControllerのModelに登録したオブジェクトがnullかどうかで表示する内容が変わります。

index.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <title th:text="${title}">title</title>
    <link href="/css/style.css" rel="stylesheet">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  </head>
  <body>
    <p>本屋さん</p>
    <form action="/book/search" method="post">
        <label>ID:<input class="input" type="text" name="id"></label><br>
        <div><input class="search" type="submit" value="検索"/></div>
    </form>
    <form action="/book/search" method="post">
        <div><input class="list" type="submit" name="showList" value="一覧表示"/></div>
    </form>

    <div th:if="${book} !=null" th:object="${book}">
        <table>
            <tr>
                <th>ID</th>
                <th>書籍名</th>
                <th></th>
                <th>著者名</th>
                <th>刊行日</th>
            </tr>
            <tr>
                <td th:text="*{id}">id</td>
                <td th:text="*{bookName}">書籍名</td>
                <td th:text="*{volumeNum}"></td>
                <td th:text="*{authorName}">著者名</td>
                <td th:text="*{publishedDate}">刊行日</td>
            </tr>
        </table>
    </div>

        <div th:if="${bookList} !=null">
        <table>
            <tr>
                <th>ID</th>
                <th>書籍名</th>
                <th></th>
                <th>著者名</th>
                <th>刊行日</th>
            </tr>
            <tr th:each="book:${bookList}" th:object="${book}">
                <td th:text="*{id}">id</td>
                <td th:text="*{bookName}">書籍名</td>
                <td th:text="*{volumeNum}"></td>
                <td th:text="*{authorName}">著者名</td>
                <td th:text="*{publishedDate}">刊行日</td>
            </tr>
        </table>
    </div>
  </body>
</html>

CSSよく分かりません。タグを[type=" "]で区別できたり、table thとスペース区切りで子要素を指定できたりする、ということはわかりました。。。

style.css
@charset "UTF-8";

input[type="text"]{
    width:70%;
    border-radius: 5px;
    padding: 10px;
}
input[type="submit"].search{
    border-radius: 5px;
    padding: 5px;
    margin-top: 10px;
    background-color:#99CCCC;
}

input[type="submit"].list{
    border-radius: 5px;
    padding: 5px;
    margin-top: 10px;
    background-color: #008BBB;
    color:#FFFFFF
}

table{
    width: 100%;
    margin-top: 10px;
    border-collapse: collapse;
}
table th, table td {
    border: 1px solid #ddd;
    padding: 6px;
}
table th {
  background-color: #6699FF;
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) が出た時の対処法

事象

mysqlを起動しようと思って以下のコマンドを打つ

$ mysql -u root

以下のエラーが表示
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

解決方法

サーバーが起動してないのに動くはずがない!

ちゃんと以下のコマンドを入力して

$ mysql.server restart

その後に

$ mysql -u root

で成功しました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerでやっぱりmysqlの中身プレビュー的なのしたくなっちゃった、、、

状況、、

Dockerで環境構築して、mysqlもコマンドで中入ればみれる、よしよし、、

って思っていたけど、いちいちコマンド叩くの嫌になちゃった、、

そうだ!いいのがあるじゃないか!の共有です!

https://hub.docker.com/_/mysql

方法

  • docker-compose.ymlに以下を追加 ※8081は使っていないポートでお願いします、
docker-compose.yml
  adminer:
    image: adminer
    restart: always
    ports:
      - 8081:8080
  • サービスの再構築コマンド(build)、コンテナ作成してスタート(up)、-d(コンテナに後でコマンドで入れるモードにしたい時に使用)をうつ $ docker-compose up --build -d

※上記行うとローカルで権限変えたもの元通りになったりするのでご注意ください。

  • 構築終わったら表示
    ※ipは、$ docker-machine ip defaultで調べられます。←マシーンを『default』で登録している場合
    スクリーンショット 2020-10-18 0.11.35.png

  • 必要なデータを入れてログイン
    スクリーンショット 2020-10-18 0.16.13.png

  • 後は見るのみ!です!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

データベースの操作(SQL編)

データベースの操作 ~SQL編~

  • SQLの使用方法を知る
  • データベースの基本的な操作を理解
  • テーブルの基本的な操作を理解

ターミナルでの使用方法

ターミナル
# ホームディレクトリに戻る
% cd

# MySQLに接続
% mysql -u root

Sequel Proでの使用方法

Sequel Proを使用してログインする際は、下記のように入力

9f4a2951092ddd67c27a8afcdc73d3d3.png

ターミナルで以下のSQLを実行

ターミナル
mysql> CREATE DATABASE sqltest;

MySQLで以下のSQL文を実行

ターミナル
mysql> SHOW DATABASES;

データベースを削除

ターミナル
mysql> DROP DATABASE sqltest;

データベースを指定

データベースを作成して、選択

ターミナル
mysql> CREATE DATABASE sqltest;
Query OK, 1 row affected (0.00 sec)

コマンドでテーブルを作成

ターミナル
mysql> CREATE TABLE goods (id INT, name VARCHAR(255));

作成したテーブルを表示

ターミナル
mysql> SHOW TABLES;

テーブルの構造を確認

ターミナル
mysql> SHOW columns FROM goods;

カラムを追加

ターミナル
mysql> ALTER TABLE goods ADD (price int, zaiko int);

カラムを変更

ターミナル
mysql> ALTER TABLE goods CHANGE zaiko stock int;

カラムを削除

ターミナル
mysql> ALTER TABLE goods DROP stock;

現場からは以上です!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む