- 投稿日:2020-11-21T23:16:02+09:00
SQL初心者〜中級者のための練習問題&解答例1
SQL初心者〜中級者のための練習問題+解答例をいくつか作ってみました。
SQL力向上のためにお役立てください。その2: SQL初心者〜中級者のための練習問題&解答例2
その3: SQL初心者〜中級者のための練習問題&解答例3ツールの紹介
DB Fiddleを使うとブラウザ上で簡単にSQLを実行できます。
画面左側のSchema SQLにスキーマを、画面右側のQuery SQLにクエリ(SELECT句)を書いて、画面上部の「Run」ボタンを押すだけです。
環境構築要らないので便利です。題材
学生テーブル
学籍番号 氏名 性別 0001 長岡 一馬 男 0002 中本 知佳 女 0003 松本 義文 男 0004 佐竹 友香 女 試験結果テーブル
学籍番号 教科 点数 0001 国語 30 0001 英語 30 0002 国語 70 0002 数学 80 0003 理科 92 0004 社会 90 0004 理科 35 0004 英語 22
Schema SQL
CREATE TABLE `students` ( `id` int(4) unsigned zerofill NOT NULL AUTO_INCREMENT PRIMARY KEY, `name` varchar(255) NOT NULL, `gender` varchar(1) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; INSERT INTO `students` (`id`, `name`, `gender`) VALUES (0001, '長岡 一馬', '男'), (0002, '中本 知佳', '女'), (0003, '松本 義文', '男'), (0004, '佐竹 友香', '女'); CREATE TABLE `exam_results` ( `student_id` int(4) unsigned zerofill NOT NULL, `subject` varchar(255) NOT NULL, `score` bigint(20) unsigned NOT NULL, PRIMARY KEY(`student_id`, `subject`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; INSERT INTO `exam_results` (`student_id`, `subject`, `score`) VALUES (0001, '国語', 30), (0001, '英語', 30), (0002, '国語', 70), (0002, '数学', 80), (0003, '理科', 92), (0004, '社会', 90), (0004, '理科', 35), (0004, '英語', 22);問1
性別が男である生徒の名前を一覧で表示せよ。
name 長岡 一馬 松本 義文
解答例
SELECT name FROM students WHERE gender = '男'問2
1教科でも30点以下の点数を取った生徒の名前を一覧で表示せよ。
ただし、重複は許さないものとする。
name 長岡 一馬 佐竹 友香
解答例
SELECT DISTINCT s.name FROM exam_results er INNER JOIN students s ON er.student_id = s.id WHERE er.score <= 30問3
性別ごとに、最も高かった試験の点数を表示せよ。
gender max_score 男 92 女 90
解答例
SELECT s.gender, MAX(er.score) AS max_score FROM students s INNER JOIN exam_results er ON s.id = er.student_id GROUP BY s.gender問4
教科ごとの試験の平均点が50点以下である教科を表示せよ。
subject avg_score 国語 50.0000 英語 26.0000
解答例
SELECT subject, AVG(score) AS avg_score FROM exam_results GROUP BY subject HAVING AVG(score) <= 50問5
試験結果テーブルの点数の右に、その教科の平均点を表示せよ。
student_id subject score subject_avg_score 0001 国語 30 50.0000 0001 英語 30 26.0000 0002 国語 70 50.0000 0002 数学 80 80.0000 0003 理科 92 63.5000 0004 理科 35 63.5000 0004 社会 90 90.0000 0004 英語 22 26.0000
解答例
SELECT er1.*, ( SELECT AVG(er2.score) FROM exam_results er2 WHERE er1.subject = er2.subject ) AS subject_avg_score FROM exam_results er1問6
試験結果に理科が含まれない生徒の名前を一覧で表示せよ。
name 長岡 一馬 中本 知佳
解答例
SELECT s.name FROM students s INNER JOIN exam_results er ON s.id = er.student_id GROUP BY s.id HAVING SUM(CASE WHEN er.subject = '理科' THEN 1 ELSE 0 END) = 0
- 投稿日:2020-11-21T23:06:55+09:00
前年度と比較を行う
年と売り上げを持つテーブルがある。
select * from sales; +------+------+ | year | sale | +------+------+ | 1990 | 50 | | 1991 | 51 | | 1992 | 52 | | 1993 | 52 | | 1994 | 50 | | 1995 | 50 | | 1996 | 49 | | 1997 | 55 | +------+------+前年度の売り上げと比較し、結果に応じた出力を行う。
select s1.year ,s1.sale ,case when sale = ( select sale from sales s2 where s2.year = s1.year -1 ) then '→' when sale > ( select sale from sales s2 where s2.year = s1.year -1 ) then '↑' when sale < ( select sale from sales s2 where s2.year = s1.year -1 ) then '↓' else '-' end as var from sales s1 order by year; +------+------+-----+ | year | sale | var | +------+------+-----+ | 1990 | 50 | - | | 1991 | 51 | ↑ | | 1992 | 52 | ↑ | | 1993 | 52 | → | | 1994 | 50 | ↓ | | 1995 | 50 | → | | 1996 | 49 | ↓ | | 1997 | 55 | ↑ | +------+------+-----+相関サブクエリの結合条件で-1とすることで
前年度のレコードを比較対象としている。次は時系列に歯抜けがある場合
select * from sales2; +------+------+ | year | sale | +------+------+ | 1990 | 50 | | 1992 | 50 | | 1993 | 52 | | 1994 | 55 | | 1997 | 55 | +------+------+select s1.year ,s1.sale ,case when sale = ( select sale from sales2 s2 where year = ( select max(year) from sales s3 where s1.year > s3.year ) ) then '→' when sale > ( select sale from sales2 s2 where year = ( select max(year) from sales s3 where s1.year > s3.year ) ) then '↑' when sale < ( select sale from sales2 s2 where year = ( select max(year) from sales s3 where s1.year > s3.year ) ) then '↓' else '-' end as var from sales2 s1 +------+------+-----+ | year | sale | var | +------+------+-----+ | 1990 | 50 | - | | 1992 | 50 | - | | 1993 | 52 | ↑ | | 1994 | 55 | ↑ | | 1997 | 55 | - | +------+------+-----+上記2つのSQLでは3回サブクエリを実行しているが、
1つにまとめられるようだ。SELECT S1.year ,S1.sale ,CASE SIGN(sale - ( SELECT sale FROM Sales S2 WHERE S2.year = S1.year - 1) ) WHEN 0 THEN '→' /* 横ばい */ WHEN 1 THEN '↑' /* 成長 */ WHEN -1 THEN '↓' /* 後退 */ ELSE '-' END AS var FROM Sales S1 ORDER BY year;こちらを参考にさせていただきました。
達人に学ぶSQL徹底指南書 第2版 初級者で終わりたくないあなたへ
- 投稿日:2020-11-21T20:46:50+09:00
MySQLと MariaDBの比較
RDBのMySQLとMariaDB
どちらも開発者は同じでMyは長女、Mariaは次女の名前だそう。
MySQL
- MySQL自体の歴史が長く、現在はIT大手のOracle社が開発を担当しているので安心感がある。
- CMS(コンテンツ・マネジメント・システム)に積極的に採用されている。Wordpressなど。
- 「Youtube」や「Netflix」が使用している。
MariaDB
- MySQLの派生でビッグデータの集計を得意としている。
- 冗長構成(情報システムなどの構成の一種で、設備や装置を複数用意し、一部が故障しても運用を継続できるようにしたもの。)を構築できる仕組みが提供されている。
- クラスタ構成(複数のサーバを連携させて利用者や他のサーバから、全体で1台のサーバであるかのように動作させる技術)データベース構築を行える。
- 負荷分散の仕組みが提供されている。
- 「SAMSUNG」や「NOKIA」が使用している。
まとめ
MariaDBの方がMySQLよりも高スペックな上に多機能である。
大きなデータを扱う時にはMariaDBの方が高速に処理できる。参考
https://www.winserver.ne.jp/column/about_mariadb/
https://style.potepan.com/articles/19653.html#MySQLMariaDB-2
- 投稿日:2020-11-21T15:35:58+09:00
ユニーク制約のキーの長さに制限がある場合の重複チェックについての確認(MySQL)
やりたいこと
MySQL 8.0で2つの文字列を格納する列(VARCHAR(2000))を持つテーブルを作成して、その2つの列の組み合わせにユニーク制約を設定したい。
例えばSQLで書くと以下のとおり。CREATE TABLE testtable ( id INT PRIMARY KEY, text1 VARCHAR(2000), text2 VARCHAR(2000), UNIQUE (text1, text2) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;ただし、これを実行すると以下のようなエラーとなってしまう。
ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytesこのエラーが出る理由であるが、ユニーク制約を設定すると自動的にインデックスが作成され、以下の制限(公式のドキュメント)に引っ掛かっているためである。
The index key prefix length limit is 3072 bytes for InnoDB tables that use DYNAMIC or COMPRESSED row format.
※ デフォルトではDYNAMIC row formatである。
utf8mb4では1文字4バイトなので、インデックスのキーの長さが合計768文字まで許されるはずである。合計768文字に制限した以下のSQLは成功して、テーブルが作成される。(この例では2つの列ぞれぞれで先頭384文字をキーとして使用するよう設定している。)
mysql> CREATE TABLE testtable ( -> id INT PRIMARY KEY, -> text1 VARCHAR(2000), -> text2 VARCHAR(2000), -> UNIQUE (text1(384), text2(384)) -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; Query OK, 0 rows affected (0.04 sec)また、実際に確認してみると、インデックスが作成されている。
mysql> show index from testtable; +-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression | +-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | testtable | 0 | PRIMARY | 1 | id | A | 0 | NULL | NULL | | BTREE | | | YES | NULL | | testtable | 0 | text1 | 1 | text1 | A | 0 | 384 | NULL | YES | BTREE | | | YES | NULL | | testtable | 0 | text1 | 2 | text2 | A | 0 | 384 | NULL | YES | BTREE | | | YES | NULL | +-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ 3 rows in set (0.01 sec)疑問点
ここまで来て疑問に思ったのは、ユニークであるかどうかの判断は、INSERTしようとしているその列の値全てではなく、ユニークインデックスのキーの長さの部分によって判断されるのではないかということである。机上で調査したが確証は得られなかったので、実機で試してみることにした。
試行
環境
Ubuntu 20.04.1 LTSおよびMySQL 8.0.22である。
stack@stack:~$ lsb_release -d Description: Ubuntu 20.04.1 LTS stack@stack:~$ mysql --version mysql Ver 8.0.22-0ubuntu0.20.04.2 for Linux on x86_64 ((Ubuntu)) stack@stack:~$ mysqld --version /usr/sbin/mysqld Ver 8.0.22-0ubuntu0.20.04.2 for Linux on x86_64 ((Ubuntu))試行結果
以下が試行結果である。
ユニークであるかどうかの判断は、ユニークインデックスのキー長によって決まり(今回の場合はtext1が5character、text2が5character)、その長さより後の文字は重複しているかどうかの判断では用いられないようである。mysql> CREATE TABLE shorttable ( -> id INT PRIMARY KEY, -> text1 VARCHAR(2000), -> text2 VARCHAR(2000), -> UNIQUE (text1(5), text2(5)) -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; Query OK, 0 rows affected (0.04 sec) mysql> INSERT shorttable values (1, 'AAAAAAAAAA', 'BBBBBBBBBB'); Query OK, 1 row affected (0.01 sec) mysql> INSERT shorttable values (2, 'AAAAA=====', 'BBBBB@@@@@'); ERROR 1062 (23000): Duplicate entry 'AAAAA-BBBBB' for key 'shorttable.text1'
- 投稿日:2020-11-21T12:54:50+09:00
諦めないのが俺の魔法だ!!絶対にリモートサーバーからDB情報を取得してインポートしてみせる!!
案件の保守対応で環境構築の際に
DB情報を用意されておらず
開発で利用していたサーバーから
DB情報を取ってきてローカルで反映させるために
今回行った内容を忘備録としてまとめておく。余談ですが、ガチの現役エンジニアは本当にすごい
相談でちょいと質問したら悩んでいる原因を明確化(整頓)してもらった上で
回答を貰える
答えを教えるのは悪!とは言いませんが
考えもせずに答えを教えて貰うのと
なぜ悩んでいるのかを明確にしてもらってから教えてもらうとでは
理解度と腹落ち度が断然変わってきますね(о´∀`о)それでは本題へ!
リモートサーバーのDB情報が欲しい
まずはリモートサーバーへログイン
sshで〜のくだりは別途調べてみて下さい!
ログインできたら次に
MySQLへのログインをして求めているDB情報があるのか確認をしよう!$ mysql -u ユーザ名 -p上記を入力してEnterを押すと
パスワードが求められるので入力してEnter
ログインができると[$]が[mysql>]に変わるのでそうなれば成功mysql>次にDB情報を一覧で確認する
mysql> show tables;すると一覧で表示されるのでそのDBの名前を控えておく
もし必要であればテーブル情報も確認できるので参考にしてみて下さいmysql> use db_name; mysql> show tables;そしたら次はそのテーブル情報をファイルにしていきます
mysql> quit //またはexit mysql> show tables;MySQLから抜けることが必要です!
自分はこれを知らずに
ずっとMySQL内でdumpしようとしてエラー出しまくってました
抜けたら次に$ mysqldump -u USER_NAME -p -h HOST_NAME DB_NAME > OUTPUT_FILE_NAMEそれぞれの必要項目が間違っていなければ
このコマンドを入力した階層内でファイルが作成されますここまででリモートサーバーでの作業は終わりなのですが
出る前に求めているファイルのパスだけ確認しておくとあとの作業が楽になりますねローカルでの作業
ローカルであればどこでもいいと思うのですが僕は今回デスクトップに
ファイルをダウンロードしてくる操作をしました$ scp [オプション] [接続ユーザ]@ホスト名(IPアドレス):コピー元 コピー先それぞれの情報を理解しておけばこちらもさくっと打って
ダウンロードができます!
終わったらDBをインポートさせるんですが
僕は今回、Sequel Proを使ってインポートをしたのですが
順番を間違えるとあれ?できない??ってなるので気をつけましょう!
- まずはDBを作っておく
- 作ったDBを選択しておく
- インポートが活性化されるので指定のファイルをインポート
これで今回求めていた作業が完了しました!
覚えてしまえば10前後で終えれそうな内容でしたね
ちなみに僕は1時間前後かかってましたので
時間を無駄にしないように気をつけましょう(о´∀`о)
- 投稿日:2020-11-21T11:59:49+09:00
【いくつ知ってる?】MySQLでCRUD操作のクエリまとめ【超基本】
最近
MySQL
にどっぷり浸かって学習しているのですが、ある程度知識のストックもできたのでアウトプットがてら、超基本的なCRUD操作のクエリについて、まとめて行きたいと思います。
目次
- CRUDについて
- Create
- Read
- Update
- Delete
CRUDについて
まず初めに、CRUD(クラッド)とは目次でも書きましたが、
- Create(作成)
- Read(参照)
- Update(更新)
- Delete(削除)
と言う、Webサービスなどで最も基本的な機能の事を指します。
例えばツイッターなんかでも、ツイートを
作成
し、それをフォロワーなどが見る(参照)
ことができます。そして、プロフィールなどの部分を随時更新
する事ができ、不要なツイートやアカウントは削除
する事ができます。このような基本的な機能の事を総称して生まれたのが、CRUDと言う言葉になります。次からは、このCRUD操作をMySQLのクエリでどのように行っていくのかを、説明していこうと思います。
Create
CREATE句
-- EXampleデータベースを作成。 CREATE DATABASE EXample; -- Exampleテーブルの作成。 CREATE TABLE Example ( id INT(10) not null auto_increment primary key, name VARCHAR(255) not null, age INT(3) );テーブルの作成について、細かい事は省きますが、括弧の中は1行につき、1カラム(縦列)の設定を行っています。表で書くとこんな感じですね。
id name age
INSERT句
-- Exampleテーブルにレコードを追加。 INSERT INTO Example VALUES (1, "Abe", 32);レコード(横列)の作成(追加)。カラムの並びに応じて、カンマ区切りでデータを記述します。実行後はこんな感じですね。
id name age 1 Abe 32
複数行を一気にいれる場合はこちら。
-- Exampleテーブルに複数レコードを追加。 INSERT INTO Example VALUES (2, "Ide", 37), (3, "Hide", 21);実行後はこんな感じです。
id name age 1 Abe 32 2 Ide 37 3 Hide 21
Read
SHOW句
-- データベースの一覧 SHOW DATABASES; -- テーブルの一覧 SHOW TABLES; -- Exampleテーブルのカラム情報一覧 SHOW COLUMNS FROM Example;個人的にはテーブルの一覧を確認する事が多いですね。ECサイトのDBとかになるとテーブルが10個近くあったりするので、いちいち覚えてられません。(笑)
SELECT句
-- Exampleテーブルの全カラムを取得。 SELECT * FROM Example; -- Exampleテーブルのnameカラムを取得。 SELECT name FROM Example; -- Exampleテーブルのidカラム、nameカラムを取得。 SELECT id, name FROM Example;最も基本的な
SELECT句
の使い方です。全カラム情報の取得なんかは、よく使います。
WHERE句
-- Exampleテーブルで、ageが32の全カラムを取得。 SELECT * FROM Example WHERE age = 32;
WHERE句
は主に条件指定をする際に使用します。情報を取得する時は、条件を絞って取得することがほとんどなので、こちらは超頻出ですね。実行して取得できるのは、こんな感じですね。
id name age 1 Abe 32
Update
UPDATE句
-- Exampleテーブルでageカラムを、全て50に変更。 UPDATE Example SET age = 50; -- Exampleテーブルでidが1のageカラムを、50に変更。 UPDATE Example SET age = 50 WHERE id = 1;使うのは下の方ですね。特定のレコードの情報を更新したい時なんかに使用。あと紹介しといてあれですが、上はほぼ使わないです。(笑)
Delete
DELETE句
-- Exampleテーブルの全レコードを削除。(テーブル自体は残る) DELETE FROM Example; -- Exampleテーブルの id=1 に一致したレコードを削除。 DELETE FROM Example WHERE id=1;こちらも使うのは下の方ですね。上は実行しようとすると、逆にセーフティ設定で弾かれることがあります。
DROP句
-- Exampleテーブルをオブジェクトごと完全に削除。 DROP TABLE Example; -- EXampleデータベースの削除。 DROP DATABASE EXample;こちらは不要になったテーブルやデータベースを削除したい時に使いますね。ただ、一度構築して運用を始めたら、余程の事がない限りは使わないかと。
まとめ
基本的なCRUD操作は、以上の内容である程度できるかと。ただ、
SELECT句
に関しては、WHERE句
以外にも使えるクエリが沢山あります。(曖昧な検索をするLIKE句
など)気になる方は是非、本格的に学習してみてください!
最後まで読んでいただき、ありがとうございました!
筆者:yuki|学習10日目で初案件獲得→現在はフルスタックエンジニア転職に向けて学習中
Qiita:https://qiita.com/yuki4839
Twitter:https://twitter.com/yuki35522891
- 投稿日:2020-11-21T10:22:50+09:00
途中でDBを変更する方法
gemにある既存のDBを変更
$ bundle install↓
config/database.ymlにある既存のDBを変更
↓$ rake db:create $ rake db:migrate== 20201120000030 CreateUsers: migrating ====================================== -- create_table(:users) -> 0.1683s == 20201120000030 CreateUsers: migrated (0.1690s) ============================= == 20201120004112 AddIndexToUsersEmail: migrating ============================= -- add_index(:users, :email, {:unique=>true}) -> 0.1129s . . . .完了。
一言: gemファイルだけ変更すればいいと思っていました。database.ymlも変更する必要があると知りました。
参考:
https://stackoverflow.com/questions/52477636/gemloaderror-error-loading-the-sqlite3-active-record-adapter
https://qiita.com/pchatsu/items/a7f53da2e57ae4aca065
- 投稿日:2020-11-21T07:41:18+09:00
GO gorm DB作成 INSERT JSONUnmarshal Mysql
こんにちは! GO学習中です!
今回はgormでinsertしてみたいと思います!
データは前回getしたapi
のデータを使用します。DB自体をGOから作成した記事はこちらです。
では始めていきたいと思います。
mysql.go
// root/app/models/fgi.go package mysql import ( "database/sql" _ "github.com/go-sql-driver/mysql" "github.com/jinzhu/gorm" ) // SQLConnect DB接続 func SQLConnect() (database *gorm.DB, err error) { DBMS := "mysql" USER := "root" PASS := "" PROTOCOL := "tcp(localhost:3306)" DBNAME := "テーブル名" CONNECT := USER + ":" + PASS + "@" + PROTOCOL + "/" + DBNAME + "?charset=utf8&parseTime=true&loc=Asia%2FTokyo" return gorm.Open(DBMS, CONNECT) }ここではDBはすでに作成しているものとします。
gormとはGOのORMパッケージです。SQLConnect()の関数ではDBの情報を宣言して、
return gorm.Open(DBMS, CONNECT)
とすることでdbと接続しています。
DB情報はConfigなどにまとめたほうが良いかもしれません。今回はルートユーザーで行なっていきます。fgi/fgi.go
こちらは冒頭紹介した記事
でgetしているapiのファイルです。上記の記事ではgetしただけでしたが、こちらでは
json.Unmarshalをすることで、用意した構造体に格納しています。構造体はこちらの json-to-go
というサイトで簡単に用意できます。左側にapiのjsonを貼り付けるとコード内のstructを用意してくれます。
package fgi import ( "encoding/json" "io/ioutil" "log" "net/http" ) // APIClientFgi api情報格納 type APIClientFgi struct { key string host string httpClient *http.Client } // New struct生成 func New(key, host string) *APIClientFgi { fgiClient := &APIClientFgi{key, host, &http.Client{}} return fgiClient } // StructFgi fgi格納 type StructFgi struct { Fgi struct { Current struct { Value int `json:"value"` ValueText string `json:"valueText"` } `json:"now"` PreviousClose struct { Value int `json:"value"` ValueText string `json:"valueText"` } `json:"previousClose"` OneWeekAgo struct { Value int `json:"value"` ValueText string `json:"valueText"` } `json:"oneWeekAgo"` OneMonthAgo struct { Value int `json:"value"` ValueText string `json:"valueText"` } `json:"oneMonthAgo"` OneYearAgo struct { Value int `json:"value"` ValueText string `json:"valueText"` } `json:"oneYearAgo"` } `json:"fgi"` } // GetFgi api実行 func (fgi *APIClientFgi) GetFgi() (StructFgi, error) { url := "https://fear-and-greed-index.p.rapidapi.com/v1/fgi" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("x-rapidapi-host", fgi.host) req.Header.Add("x-rapidapi-key", fgi.key) res, err := http.DefaultClient.Do(req) if err != nil { return StructFgi{}, nil } defer res.Body.Close() body, err := ioutil.ReadAll(res.Body) if err != nil { return StructFgi{}, nil } var fgiStruct StructFgi if err := json.Unmarshal(body, &fgiStruct); err != nil { log.Fatal(err) } return fgiStruct, nil }json-to-goで生成したstructを呼び出しjson.Unmarshalでstructに格納しています。
models/fgi.go
このファイルでは上記でstructに格納したapi情報を展開してDBにINSERTしていきます。
package models import ( "fmt" "index-indicator-apis/mysql" "time" "index-indicator-apis/config" "index-indicator-apis/fgi" ) const ( tableNameFgis = "fgis" ) // Fgis 日足格納 type Fgis struct { CreatedAt time.Time `json:"created_at,omitempty"` NowValue int `json:"now_value,omitempty"` NowText string `json:"now_text,omitempty"` PcValue int `json:"pc_value,omitempty"` PcText string `json:"pc_text,omitempty"` OneWValue int `json:"one_w_value,omitempty"` OneWText string `json:"one_w_text,omitempty"` OneMValue int `json:"one_m_value,omitempty"` OneMText string `json:"one_m_text,omitempty"` OneYValue int `json:"one_y_value,omitempty"` OneYText string `json:"one_y_text,omitempty"` } //initFgis マイグレーション func initFgis() { var err error db, err := mysql.SQLConnect() if err != nil { panic(err.Error()) } defer db.Close() db.AutoMigrate(&Fgis{}) } // NewFgis fgi.StructFgiを受け取り、Fgisに変換して返す func NewFgis(f fgi.StructFgi) *Fgis { createdAt := time.Now() nowValue := f.Fgi.Current.Value nowText := f.Fgi.Current.ValueText pcValue := f.Fgi.PreviousClose.Value pcText := f.Fgi.PreviousClose.ValueText oneWValue := f.Fgi.OneWeekAgo.Value oneWText := f.Fgi.OneWeekAgo.ValueText oneMValue := f.Fgi.OneMonthAgo.Value oneMText := f.Fgi.OneMonthAgo.ValueText oneYValue := f.Fgi.OneYearAgo.Value oneYText := f.Fgi.OneYearAgo.ValueText return &Fgis{ createdAt, nowValue, nowText, pcValue, pcText, oneWValue, oneWText, oneMValue, oneMText, oneYValue, oneYText, } } // Create NewFgisをsaveする func (f *Fgis) Create() error { db, err := mysql.SQLConnect() if err != nil { panic(err.Error()) } defer db.Close() db.Create(&f) return err } // CreateNewFgis migration後にapiを叩きdbに保存する func CreateNewFgis() error { // initFgis() migration fgiClient := fgi.New(config.Config.FgiAPIKey, config.Config.FgiAPIHost) f, err := fgiClient.GetFgi() if err != nil { return err } fgi := NewFgis(f) fmt.Println(fgi) fmt.Println(fgi.Create()) return err }initFgis()ではgormのメソッドをつかってマイグレーションしています。
apiの情報を先ほどstructに格納したので、それを展開してさらに展開したvalueを格納するstructを用意するということですね。
db.AutoMigrate(&Fgis{})
こちらがgormのメソッド AutoMigrateメソッドです。
事前に用意した構造体の名前をテーブル名としてマイグレーションしてくれます。この場合だと
fgisというテーブルがmysqlに作成されます。
func NewFgis(f fgi.StructFgi) *Fgis{}
こちらではapiのデータを格納している StructFgiの中身を展開してINSERTするために用意した構造体(マイグレーションした)の中に格納してます。
func (f *Fgis) Create() error {}
こちらのメソッドではmysqlファイルで作成した関数のSQLConnect()でdbと接続後に
db.Create(&f)
とすることでINSERTを実現しています。 .Createがgormのメソッドです。 .Create(&struct)とすることでテーブル名と対応しているstructの情報をINSERTしてくれます。最後に
CreateNewFgis()
で用意した関数とメソッドを実行しています。この関数をmain.goから呼び出せば無事に実行されることができました。
- gormでは主キーとなるIDは自動で生成されるので宣言する必要はありません。
以上です!