20210502のMySQLに関する記事は8件です。

DockerでMysqlのコンテナに入る

コンテナ内に入る ①docker ps もしくは ②docker-compose ps でコンテナIDを確かめる。 ① $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7d323ba6b1b8 mysql:5.7 "docker-entrypoint.s…" 51 minutes ago Up 51 minutes 3306/tcp, 33060/tcp hogelog_db_1 $ docker exec -it < コンテナID > sh (shもしくはbash) $ docker exec -it 7d323ba6b1b8 sh ② % docker-compose ps Name Command State Ports -------------------------------------------------------------------------------------------- hogelog_db_1 docker-entrypoint.sh mysqld Up 0.0.0.0:4306->3306/tcp, 33060/tcp $ docker exec -it < コンテナNAME > sh (shもしくはbash) $ docker exec -it hogelog_db_1 sh コンテナ内に入れたら # mysql -u root -p Enter password: パスワードを要求されるので、docker-compose.ymlに記述してあるパスワードを入力する。 mysql> 接続完了。 mysql> exit Bye
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Sự chuyển biến bất ngờ của đất nền thị xã Phú Mỹ

Đất nền thị xã Phú Mỹ hay bất động sản Phú Mỹ trong những thời gian gầy đây có những biến động cực kì tích cực. Tuy cũng là một khu vực ngay gần kề TP.HCM như Bình Dương, Biên Hoà,.. thế nhưng thị xã Phú Mỹ lại mang trong mình cực nhiều lợi thế vượt trội. Với rất nhiều sức hút to lớn tới từ sân bay Long Thành, Cảng Cái Mép. Giá các dự án đất nền có bằng chung nếu so với các khu vực khác là hợp lí. Giá thông thường ở các TP,Vũng Tàu, TP.Bà Rịa thường cao gấp 3-4 lần so với đất nền Phũ Mỹ. Trong khi lợi thế vị trí của Phú Mỹ cũng không hề kém cạnh. https://diaocbariavungtau.com/dat-nen-thi-xa-phu-my/
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MySQL InnoDB Cluster練習

MySQL 8.0.13 で MySQL InnoDB Cluster を構築する | スマートスタイル TECH BLOG|データベース&クラウドの最新技術情報を配信 の写経 所感 従来のようなレプリケーション設定ではファイル変更必須だったが、コマンド実行だけで構築簡単 nodeがダウンすると良い感じにプライマリが切り替わる 復帰すると良い感じにセカンダリへ 如何せんまだまだWebにノウハウが多いとは言えない routerがいればnodeがダウンしても自動的に接続先を切り替えてくれるが、router自体の冗長化はどうするのかとなるが、各アプリケーション・サーバーにrouterを入れるのが正解? 構成 docker-composeでOSはAlmaLinux8。(あえて公式mysqlコンテナを使わず) mysqlのバージョンはmysql-server-8.0.21(現在最新) マシン IP ホスト名 MySQL Shell 172.30.0.2 shell MySQL Router 172.30.0.3 router MySQL Server (node1) 172.30.0.11 node1 MySQL Server (node2) 172.30.0.12 node2 docker-composeファイル docker-compose.yml # vim: set ts=2 et: version: '3.5' services: shell: image: almalinux/almalinux:8 hostname: shell privileged: true command: /sbin/init networks: app_net: ipv4_address: 172.30.0.2 router: image: almalinux/almalinux:8 hostname: router privileged: true command: /sbin/init networks: app_net: ipv4_address: 172.30.0.3 node1: image: almalinux/almalinux:8 hostname: node1 privileged: true command: /sbin/init networks: app_net: ipv4_address: 172.30.0.11 node2: image: almalinux/almalinux:8 hostname: node2 privileged: true command: /sbin/init networks: app_net: ipv4_address: 172.30.0.12 networks: app_net: name: app_net driver: bridge ipam: driver: default config: - subnet: 172.30.0.0/24 ※ポート3306を公開していないのでアクセスできないのはとりあえず気にしない 各サーバーへのログインは docker-compose exec node1 /bin/bash 構築 // node1~2で実行 # dnf install -y https://dev.mysql.com/get/mysql80-community-release-el8-1.noarch.rpm # dnf install -y mysql-server # systemctl start mysqld # mysql mysql> create user 'root'@'172.30.0.%' identified by 'Password1!'; mysql> grant all on *.* to 'root'@'172.30.0.%' with grant option; // shellで実行 # dnf install -y https://dev.mysql.com/get/mysql80-community-release-el8-1.noarch.rpm # dnf install -y mysql-shell // MySQL Group Replication の各インスタンスの設定 # mysqlsh MySQL JS> dba.configureInstance('root@node1') Do you want to perform the required configuration changes? [y/n]: y Do you want to restart the instance after configuring it? [y/n]: y MySQL JS> dba.configureInstance('root@node2') Do you want to perform the required configuration changes? [y/n]: y Do you want to restart the instance after configuring it? [y/n]: y MySQL JS> dba.checkInstanceConfiguration('root@node1') MySQL JS> dba.checkInstanceConfiguration('root@node2') // MySQL Group Replication のクラスターを組む MySQL JS> \c root@node1 MySQL JS> cluster = dba.createCluster('mycluster') MySQL JS> cluster.addInstance('root@node2') MySQL JS> cluster.status() // 二回目接続時 # mysqlsh MySQL JS> \c root@node1 MySQL JS> cluster = dba.getCluster() MySQL JS> cluster.status() // routerで実行 # dnf install -y https://dev.mysql.com/get/mysql80-community-release-el8-1.noarch.rpm # dnf install -y mysql-router-community # mysqlrouter --bootstrap root@node1 --user=mysqlrouter ## MySQL Classic protocol - Read/Write Connections: localhost:6446 - Read/Only Connections: localhost:6447 ## MySQL X protocol - Read/Write Connections: localhost:6448 - Read/Only Connections: localhost:6449 # systemctl start mysqlrouter // (mysqlコマンドが入っていればどこからでもよいので)routerに接続 # mysql -u root -p -h router -P 6446 --prompt="mysql-\p> " mysql-6446> 確認 // mode1で実行 # mysql mysql> SELECT * FROM performance_schema.replication_group_members; +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+ | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+ | group_replication_applier | 607e2f00-ab3e-11eb-9608-0242ac1e000b | node1 | 3306 | ONLINE | PRIMARY | 8.0.21 | | group_replication_applier | 6167af21-ab3e-11eb-853a-0242ac1e000c | node2 | 3306 | ONLINE | SECONDARY | 8.0.21 | +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+ 2 rows in set (0.00 sec) // shellで実行 # mysqlsh MySQL JS> \c root@node1 MySQL JS> cluster = dba.getCluster() MySQL JS> cluster.status() { "clusterName": "mycluster", "defaultReplicaSet": { "name": "default", "primary": "node1:3306", "ssl": "REQUIRED", "status": "OK_NO_TOLERANCE", "statusText": "Cluster is NOT tolerant to any failures.", "topology": { "node1:3306": { "address": "node1:3306", "memberRole": "PRIMARY", "mode": "R/W", "readReplicas": {}, "replicationLag": null, "role": "HA", "status": "ONLINE", "version": "8.0.21" }, "node2:3306": { "address": "node2:3306", "memberRole": "SECONDARY", "mode": "R/O", "readReplicas": {}, "replicationLag": null, "role": "HA", "status": "ONLINE", "version": "8.0.21" } }, "topologyMode": "Single-Primary" }, "groupInformationSourceMember": "node1:3306" } MySQL JS> cluster.listRouters() { "clusterName": "mycluster", "routers": { "router::system": { "hostname": "router", "lastCheckIn": null, "roPort": 6447, "roXPort": 6449, "rwPort": 6446, "rwXPort": 6448, "version": "8.0.24" } } } CentOSにMySQLのインストール/アンインストール - Qiita MySQL 8.0.13 で MySQL InnoDB Cluster を構築する | スマートスタイル TECH BLOG|データベース&クラウドの最新技術情報を配信 docker-composeで作成されるものの名前を明示的に指定する方法 - Qiita docker-composeでコンテナの内部IPアドレスを固定化してWebサイトを作る - sagantaf MySQL InnoDB Cluster を使って運用を手抜きしよう - Speaker Deck MySQL Routerの冗長化について - 2000秒後の私へ オンラインで MySQL InnoDB Cluster の構成を変更する | スマートスタイル TECH BLOG|データベース&クラウドの最新技術情報を配信
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel8で新規プロジェクトを作成する際の手順と初期設定

0. 概要 この記事は、Laravel8で新しくプロジェクトを作る際の手順や初期設定を記したものである。Auth機能を使用しない場合は「2. Auth機能のインストール」は読み飛ばしてよい。 環境は以下の通り。 OS: windows DB: MySQL TE: VSCode 1. プロジェクトの作成 コマンドプロンプトでディレクトリを移動する。ここではデスクトップに作成する。 cd desktop 移動したディレクトリ上で以下のコマンドを入力し、プロジェクトを作成する。 laravel new プロジェクト名 2. Auth機能のインストール 2.1. jetstreamのインストール コマンドプロンプトで、1で作成したプロジェクト上にディレクトリを移動する。 cd プロジェクト名 移動したディレクトリ上で以下のコマンドを入力し、jetstreamをインストールする。 composer require laravel/jetstream 2.2. livewireのインストール 以下のコマンドでlivewireをインストールする。livewireではなくinertiaをインストールする場合は、該当箇所を書き換えればよい。team機能を利用する場合は、後ろに --teamsを書き加えればよい。 php artisan jetstream:install livewire 2.3. パッケージのビルド 以下のコマンドでパッケージをビルドする。なお、npmコマンドエラーが出る場合は事前にNode.jsをインストールしておく必要がある。 npm install && npm run dev 3. データベースの準備 3.1. データベースの作成 コマンドプロンプトで以下のコマンドを実行する。 mysql -u root -p 以下のようにパスワードを求められるので、入力する。 Enter password: ************* ログインできたら、以下のコマンドでデータベースを作成する。 create database データベース名 character set utf8; 3.2. ユーザーへの権限の付与 root権限で常にアクセスするのはセキュリティの観点から望ましくないので、新しいユーザーを作成してアクセス権限を付与するか、既にあるユーザーにアクセス権限を与えるかするためにroot権限でログインした状態から以下のコマンドを実行する。 grant all privileges on データベース名.* to ユーザー名@localhost identified by 'パスワード'; 後者の場合、identified ~以降は不要である。 3.3. .envとconfig/database.phpの修正 プロジェクト内の.envファイルをテキストエディタで開き、該当箇所を以下のように修正する。 DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=データベース名 DB_USERNAME=ユーザー名 DB_PASSWORD=パスワード 同様に、config/database.phpを開いて該当箇所を以下のように修正する。 'mysql' => [ 'driver' => 'mysql', 'url' => env('DATABASE_URL'), 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '3306'), 'database' => env('DB_DATABASE', 'データベース名'), 'username' => env('DB_USERNAME', 'ユーザー名'), 'password' => env('DB_PASSWORD', 'パスワード'), 'unix_socket' => env('DB_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'prefix_indexes' => true, 'strict' => true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), ]) : [], ], 特に、host, database, username, passwordの4つが正しいことを確認する。 3.4. マイグレーションの実行 カレントディレクトリがプロジェクト上にあることを確認し、以下のコマンドでマイグレーションを実行する。 php artisan migrate 成功すれば、usersテーブルを含む6つのテーブルが作成されていることが確認できる。 4. その他の設定 このままだと「Target class [〇〇] does not exist.」というエラーが出てしまうので、app/Providers/RouteServiceProvider.phpを開き、該当箇所を以下のように修正する。具体的には、「public function boot()」の上に、「protected $namespace = 'App\Http\Controllers';」を追加する。 protected $namespace = 'App\Http\Controllers'; public function boot() { $this->configureRateLimiting(); $this->routes(function () { Route::prefix('api') ->middleware('api') ->namespace($this->namespace) ->group(base_path('routes/api.php')); Route::middleware('web') ->namespace($this->namespace) ->group(base_path('routes/web.php')); }); }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[SQL] LeetCodeの無料問題集を活用して、SQLを使いこなし(3)

Q178 Rank Scores 質問 スコアをランク付けするSQLクエリを記述します。 2つのスコアの間に同点がある場合は、両方のランキングが同じである必要があります。 同点の場合、次のランキング番号は次の連続する整数値である必要があることに注意してください。 たとえば、上記のスコアテーブルが与えられた場合、クエリは次のレポートを生成する必要があります(最高スコアの順に並べる)。 Code書き方のHINT この問題は順位付けの関数についての理解を問われています。 REF:https://johobase.com/sqlserver-rank-denserank-rownumber-ntile/ rank(): 順位を付ける関数。 比較対象の値が同じ場合は同じ順位になり、その次は順位を飛ばします。 dense_rank(): 順位を付ける関数。 比較対象の値が同じ場合は同じ順位になり、その次は順位を飛ばしません。 row_number(): 連番ををつける関数。 比較対象の値が同じ場合であっても同じ順位にはならず、順位をカウントアップします。 イメージ図 rank関数とdense_rank関数の違いは 同じ順位になった場合、その次は順位を飛ばすかどうかです。 今回は、順位を飛ばさないと要求されているので、dense_rankを使います。 Code select Score, dense_rank() over (order by Score desc) as `Rank` from Scores Code検証結果
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

djanogoのmigrationにはまった

models.pyに子テーブルJournalistを書いてmakemigrations models.py from django.db import models class Journalist(models.Model): first_name = models.CharField(max_length=60) last_name = models.CharField(max_length=60) biography = models.TextField(blank=True) def __str__(self): return f"{self.first_name } { self.last_name }" class Article(models.Model): author = models.ForeignKey(Journalist, on_delete=models.CASCADE, related_name="articles") # author = models.CharField(max_length=50) title = models.CharField(max_length=120) description = models.CharField(max_length=200) body = models.TextField() location = models.CharField(max_length=120) publication_date = models.DateField() active = models.BooleanField(default=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return f"{self.author } { self.title }" するとエラーが発生。内容はJohnはintegerじゃないよ的な感じだった気がする。 なんの話?ってな感じでもう一回migrateするとエラーがJournalistテーブルは存在しているに変わっていた。 とりあえずmysqlを確認すると確かに存在しており、さっきのmigrateで追加されたんだろうと考えJournalistテーブルをdrop。 するとまたJohnはintegerじゃないよ的なこと言われてそこで気づいた。 テーブルarticleのauthorのデータはforeignkeyなので、integerでなければいけないはずなのに、子テーブルを作る前のデータが残っていたため、authorカラムに文字列入ってるぞと怒っていたようだ 。 そこでテーブルのデータをtruncateしておけばよかったのに、親テーブルArticleをdrop。 そして再度makemigrations、migrateの流れでやるとなぜかnothing to migrateが出る。 mysqlで確認しても明らかにテーブルは作成されていなかった。 migrationsファイル内を消したり思いつくことをある程度やってもうまくいかなかったので、migration リセットで調べると解決策が見つかった。 terminal python manage.py migrate --fake [アプリ名] zero 次にmigrationsディレクトリ内の『__ init__.py』ファイル以外のすべてのファイルを削除 あとはいつも通り terminal python manage.py makemigrations python manage.py migrate ついでに、以下のコマンドでmigrationの確認ができるっぽい terminal python manage.py showmigrations 参考にさせて頂いたサイト
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Node.js】Express.js / MySQL / ejs / を使ったDBのCRUDアプリ

目的 現在、MySQLに保管した店舗データを編集できるアプリケーションを作成しています。Node.jsのexpress.jsを使用し、viewにはejsを利用しています。この記事では、初学者の私がつまずいた、パラメータの受け渡しについて記述します。 ずばり「企業一覧画面から、企業に属した店舗の一覧を表示させる」処理についてです。 一連の処理は、こんな感じです 企業+店舗一覧を取得(MySQL) → 企業一覧画面で企業名をクリック(ejs) → 店舗一覧画面(ejs) → 店舗名のリンクをクリック (ejs) → ★ express.js(app.js)でデータを加工(MySQL) → ★ 加工したデータをejsに渡す(express.js) → ★ ejsで加工したデータを表示させる 対象読者 ・Express初心者 ・アプリ作成初心者 ・MySQL初心者 環境と周辺構造 ・local (mac Big Sur) ・AWS MySQL 基本となるデータベースとの接続やCRUD処理の基礎的な書き方等については、主にリンク先の記事を参考に作成しました。 参照:Express.js(node.js)からMySQLへの接続とCRUD操作 テーブル構造 テーブルの相関関係は以下の通りです。 account_masterが企業、shop_masterが企業が運営する店舗と仮定し作成しています。 テーブルの関係性を簡単に表すと、 account_master.account_id = shop_master.shop_account_idです。 企業側のaccount_idは店舗側のshop_account_idと同じことを意味しています。 画面イメージ 少し雑ですが、画面のイメージは以下の通りです。 ・企業 一覧画面(account_master_index.ejs) ・店舗一覧画面(shop_index) 企業名リンクをクリックすると、店舗一覧画面に遷移します。 ディレクトリ構造 ※現在、未完成のため一部のみ記載 account_app/ ├── node_modules ├── views │ ├── account_master_index.ejs │ ├── edit.ejs │ └── shop_index.ejs ├── .env ├── .gitignore ├── app.js ├── package.json └── README.md app.jsにexpress.jsやMySQLの処理を記述し、viewsの中でテンプレートを作成しています。 前提 参考サイトでは、簡易なテーブルのデータで作成されていたため、企業の一覧や、店舗の一覧は簡単に表示まで出来ました。しかし、企業に基づく店舗など関係性がちょっと複雑な場合、どう表示させればよいかが全く分かりませんでした。 先に企業一覧について、次に店舗一覧について記述します。 企業一覧画面 app.js 企業一覧画面は参考サイトを元に、テーブル名、select文を変えるだけでOKでした。※記述外の設定は参考サイトを参照ください。 //app.jsの企業一覧に関する部分 app.get('/', (req, res) => { const sql = "select * from account_master where is_deleted = 0; con.query(sql, function (err, result, fields) { if (err) throw err; res.render('account_master_index',{account_master : result}); }); }); app.getは 第一引数に指定したURLに対応しており、express.js のアプリケーションのルート( 今回は、localhost:3000 )へのGETメソッドに対応します。con.queryでselect * from account_master where is_deleted = 0"を取得。 例外処理を記述した後、res.renderの第一引数にデータを表示させたいテンプレートを設定し、第二引数に .ejs に渡す名前を指定します。この命名により、ejs側ではresultではなくaccount_masterを使って取得したデータを利用できます。 account_master_indx.ejs 一部抜粋した記述です。 //account_master_indx.ejsの中身 <% account_master.forEach(function (value) { %> <tr> <td><%= account_id %></td> ★ <td><a href="/shop_index/<%= value.account_id %>"><%= value.account_name %></a></td> <td><%= value.account_email.split('*') %></td> <td><%= value.mail_requested %></td> <td><%= value.is_deleted %></td> <td><%= value.updated_at %></td> <td><%= value.account_form_url %></td> <td><a href="/edit/<%= value.ue_account_id %>">up</a></td> </tr> <% }); %> 参考サイトはforEachを使っていたため、そのまま使っています。<% %>や、<%= %>で処理を書くのか、 HTML として表示させるかを書きます。 ★ここで4行目に注目 <a href="/shop_index/<%= value.account_id %>"><%= value.account_name %></a>で企業 id のパラメータをURLに指定しています。後にこれと同じURLのパラメータとして表示させる処理をreq.paramsを使い app.js 内に で記述します。 ここからが今回の記事の本題です ポイントとしては以下のとおりです。 ・個別に呼び出すのではなく、まず店舗の全データを取得する ・配列を新たに作成する ・for文、if文で条件指定する ・加工した「会社一覧に紐づく店舗一覧の配列を作成するデータ」をejs側で表示する app.jsでデータを加工する 失敗した考え方 店舗一覧画面を出そうした際に、まず企業一覧画面と企業の編集画面を参考にしました。というのも、編集画面は企業のaccount_idを自然に渡せていたからです。そのため、店舗一覧画面も企業一覧と編集画面のようにaccount_idを受け渡せないかと考えました。 そもそも、この↑部分の認識が間違っており、正しくはexpress.js側で処理したデータをejsで表示させる。つまり、ejsからgetメソッドで表示させる場合はejsから値を受け渡すなどは行わないです。 成功した考え方 いきなり企業に紐づく店舗一覧を、expressで記述しそれをejs側で表示させるのではなく、まずapp.js内で先に店舗の全データを出します。そのデータを使って、必要な情報だけを載せた配列を新たに作成します。作成した配列をejs側で呼び出し、表示させます。 店舗一覧画面 店舗一覧画面に関する記述は以下のとおりです。 app.js //店舗データを取得するための変数を定義 var shopDat; //店舗の全データを取得 con.query('select * from shop_master where is_deleted = 0;', function (error, results, fields) { if (error) throw error; shopDat = results; //shopDatに代入 }); ~~(中略)~~ //企業ごとの店舗一覧を取得しshop_index.ejsで表示させるためのデータ加工 app.get('/shop_index/:shop_account_id', (req, res) => { let shops = []; //新たな配列を作成 for(let i = 0; i < shopDat.length; i++){ if (req.params.shop_account_id == shopDat[i].shop_account_id) { //表示するパラメータを指定 var target_shop = { //配列に入れるオブジェクトデータを定義 "shop_id": shopDat[i].shop_id, "shop_name_jp": shopDat[i].shop_name_jp, "shop_name_en": shopDat[i].shop_name_en, "shop_account_id": shopDat[i].shop_account_id, "is_deleted": shopDat[i].is_deleted, "updated_at": shopDat[i].updated_at }; shops.push(target_shop) //空の配列shopsに.pushで追加 } }; res.render('shop_index',{shop_data :shops}); //shop_dataとしてshop_index.ejsに渡す }); 先に shopDat を宣言し、そこにMySQLから店舗の全データを代入します。店舗一覧画面を表示させる箇所に、 shops という新たな空の配列を作成します。更にi番目の shopDat のデータを保持させる target_shop というオブジェクトを作成します。shops.push(target_shop)を shops という空の配列に、 for 文で作成されたオブジェクトを追加して、加工データを作成します。 この時req.params.shop_account_id == shopDat[i].shop_account_idではURLに渡すパラメータと企業に紐づく店舗の情報を一致させるために記述しています。※shop_account_idは企業のアカウント id と同じです。 req.params はリクエストされたパスからパラメータを取得するに使う文字列です。 [Node.js][Express]リクエストからパラメータを取得する・POSTされたデータを取得する shop_index.ejs //店舗一覧画面に関係する部分 <% for (let i = 0; i < shop_data.length; i++) { %> <tr> <td><%= shop_data[i].shop_id %></td> <td><%= shop_data[i].shop_name_jp %></td> <td><%= shop_data[i].shop_name_en %></td> <td><%= shop_data[i].shop_account_id %></td> <td><%= shop_data[i].updated_at %></td> <td><a href="/edit/<%= shop_data[i].shop_id %>">更新する</a></td> </tr> <% }; %> 企業一覧画面ではforEachを使いましたが、こちらは for 文で表記しました。これで、企業に属する店舗の一覧を表示させることができました。 小技とつまずいたポイント ・出力したいデータが正しいかどうかをHTML(.ejs)でみたい → <%- JSON.stringify(shop_data) %>と記述することで見られます! ・JavaScriptのデータは配列[ ]の中にオブジェクト{ }をもつことができる。 → JavaScriptは [{ name:aaa, email:xxx@yyyy}, { name:bbb, email:yyy@xxxx}, { }....]とできるようです。 ・forとif文を一気に記述するのではなく、一つづつ書くこと → 処理を一気に書こうとして、ほしいデータをなかなか出すことが出来ませんでした。落ち着いて出力されたデータを見ながら、一つづつ解決するほうが結果早いですね。 ・配列から要素を取り出す方法 → iをつけることに、なかなか気がつけませんでした。 まとめ JavaScriptを勉強しはじめて3週間ほどですが、MySQLのデータを加工を実施しました!空の配列を作って、ほしいデータを作成をすることは初めての作業でしたが、なんとかうまく出来たので良かったです。途中で、配列なのか連想配列なのか迷ったりしたため中々答えにたどり着けませんでした。これが初学者の方のためになればと思います。 また、一部未完成・不十分な記述がありますので、ご教示いただけると幸いです! 以上 参照 ・Express.js(node.js)からMySQLへの接続とCRUD操作 ・[Node.js][Express]リクエストからパラメータを取得する・POSTされたデータを取得する ・for 文と push メソッドを使って配列要素を複数生成
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】MySQLの操作方法(Windows) その2:Javaでの操作

はじめに 前回、DBの準備編にて作成したDBを用いて JavaでのDB操作をやってみたいと思います。 前回の記事 → 【Java】MySQLの操作方法(Windows) その1:DB準備編 前提 動作環境は下記の通りです。 項目 情報 備考 Java バージョン 14.0.2 コマンドプロンプトにて java -version で確認 MySQL バージョン 8.0.24 コマンドプロンプトにて mysql --version で確認 C:\>java -version java version "14.0.2" 2020-07-14 Java(TM) SE Runtime Environment (build 14.0.2+12-46) Java HotSpot(TM) 64-Bit Server VM (build 14.0.2+12-46, mixed mode, sharing) C:\>mysql --version mysql Ver 8.0.24 for Win64 on x86_64 (MySQL Community Server - GPL) 準備 プロジェクトにJDBCドライバーを組み込みます。 ・[プロジェクト] -> [プロパティ] を選択 ・[Javaのビルド・パス] -> [ライブラリ] -> [外部JARの追加] にて、 C:\Program Files (x86)\MySQL\Connector J 8.0\mysql-connector-java-8.0.24.jar を選択し、追加します。 (パスは異なる場合がありますので、ご自身の環境に合わせてください。) 実践(Javaでの操作) 1.1 データベースへ接続 まずは、データベースへ接続してみます。 データベースへ接続するために、java.sql.Connectionのインスタンスを取得します。 今回は、DriverManagerのgetConnection()を使用して取得します。 (この他にも、DIコンテナを使用するなど様々な手法が存在する様子・・) SqlConnect.java import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class SqlConnect { public static void main(String[] args) { // データベース接続で使用する情報 final String jdbcId = "root"; // データベースへ接続するユーザ名 final String jdbcPass = "root"; // パスワード final String jdbcUrl = "jdbc:mysql://localhost:3306/sample"; // ローカル実行なので、localhostを指定。ポートもデフォルトの3306。テスト用のデータベース名のsampleを指定。 // データベースへの接続 try (Connection db = DriverManager.getConnection(jdbcUrl, jdbcId, jdbcPass)) { System.out.println("接続に成功!!"); } catch (SQLException e) { System.out.println("接続に失敗:" + e.getMessage()); } } } データベースへの接続が成功すると、コンソールに「接続に成功!!」と表示されます。 なお、データベースへの接続時のclose処理などの後片付けを自動的にしてくれる点では、try-with-resources構文を使用するのが良いらしい。 参考:try-finallyよりもtry-with-resourcesを使おう しかし、後述のトランザクション処理利用時には、 tryブロックから抜ける際に、catchブロック実行前に自動的にclose処理が動作するため、 明示的なロールバックが記述できないなどのデメリットもある様子・・・ 1.2 データベースの検索 データベース内のデータを検索し、取得します。 SqlQuery.java import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class SqlQuery { public static void main(String[] args) { // データベース接続用の情報 final String jdbcId = "root"; final String jdbcPass = "root"; final String jdbcUrl = "jdbc:mysql://localhost:3306/sample"; try (Connection db = DriverManager.getConnection(jdbcUrl, jdbcId, jdbcPass)) { PreparedStatement ps = db.prepareStatement("select * from members where sex = ?"); ps.setString(1, "女"); ResultSet rs = ps.executeQuery(); while (rs.next()) { System.out.println(rs.getString("name")); System.out.println(rs.getString("sex")); System.out.println(rs.getString("age")); System.out.println("*****************************"); } } catch (SQLException e) { System.out.println("接続に失敗:" + e.getMessage()); } } } まずは、 PreparedStatementを使用して、実行したいSQLのひな型を作成します。 後で値を入れたい部分については、?マークを記述します。(パラメータと呼ばれる) 次に、 ?部分にsetStringを使用して、具体的な値を入れます。 (今回は文字列を入れるので、setStringを使用) setString(パラメータ番号, 文字列)の形。(パラメータ番号は1から始まる。?の位置に対応) 準備ができたので、 SQL文をexecuteQueryを使用して、送信します。 結果はResultSetを使用して受け取ります。 最後に、受け取ったResultSetの中身をwhile文を用いて取り出します。 ResultSetのnextメソッドは戻り値をboolean型で返すので、値がある分だけループで取り出せます。 実行結果は下記の通りとなります。 1.3 データベースへのデータ挿入 INSERT文を用いて、データの登録を行います。 SqlUpdate.java import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; public class SqlUpdate { public static void main(String[] args) { final String jdbcId = "root"; final String jdbcPass = "root"; final String jdbcUrl = "jdbc:mysql://localhost:3306/sample"; String sql = "INSERT INTO members (id, name, sex, age) VALUES (?, ?, ?, ?)"; try (Connection db = DriverManager.getConnection(jdbcUrl, jdbcId, jdbcPass)) { PreparedStatement ps = db.prepareStatement(sql); ps.setString(1, "20210430"); ps.setString(2, "スーパー太郎"); ps.setString(3, "男"); ps.setInt(4, 35); int result = ps.executeUpdate(); System.out.println(result + "行が追加されました。"); } catch (SQLException e) { e.printStackTrace(); } } } スーパー太郎さんを追加しています。 PreparedStatementを使用して、SQLのひな型を準備し、 setString、setIntを使用して、具体的な値を入れ込む部分は検索と同じです。 SQLを送信する際のメソッドが、executeUpdateメソッドになっています。 また、戻り値は「データベースで変更された行数」となるので、int型で受けています。 実行するとこの様な感じになります。 本当に追加されたかは、1.2の検索の条件を変更して実行すれば確認できます。 変更前:ps.setString(1, "女"); 変更後:ps.setString(1, "男"); 実行すると、下記のように追加されている事が確認できます。 1.4 トランザクション処理 最後にトランザクション処理をやってみます。 なお、トランザクション処理そのものの解説は行いませんので、ググって調べてください。 SqlTransact.java import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; public class SqlTransact { public static void main(String[] args) { // データベース接続用の情報 final String jdbcId = "root"; final String jdbcPass = "root"; final String jdbcUrl = "jdbc:mysql://localhost:3306/sample"; String sql1 = "INSERT INTO members (id, name, sex, age) VALUES (?, ?, ?, ?)"; String sql2 = "INSERT INTO members (id, name, sex, age) VALUES (?, ?, ?, ?)"; try (Connection db = DriverManager.getConnection(jdbcUrl, jdbcId, jdbcPass)) { // トランザクション処理のため、自動コミットをオフ db.setAutoCommit(false); try (PreparedStatement ps1 = db.prepareStatement(sql1) ; PreparedStatement ps2 = db.prepareStatement(sql2)) { ps1.setString(1, "20210431"); ps1.setString(2, "田中春香"); ps1.setString(3, "女"); ps1.setInt(4, 20); ps1.executeUpdate(); ps2.setString(1, "20210431"); ps2.setString(2, "鈴木春香"); ps2.setString(3, "女"); ps2.setInt(4, 24); ps2.executeUpdate(); // データベースへコミット db.commit(); } catch (SQLException e) { // データベースをロールバック db.rollback(); System.out.println("処理エラー:" + e.getMessage()); } } catch (Exception e) { e.printStackTrace(); } } } トランザクション処理を行うためには、自動コミットをオフにするために データベース接続に取得したConnection(dbという変数)に対して、 setAutoCommit(false)を実行しています。 そして一連の処理が完了した後に、commit()を呼び出し、コミット処理を実行しています。 なお、途中で処理が失敗した場合には、 処理をキャンセルするために、rollback()を呼び出しています。 今回の例では、idがプライマリキーとなっているにも関わらず、 重複して登録しようとしているので、処理がエラーとなり、誰も追加されません。 (鈴木さんの追加時(ps2のほう)、エラーとなる。) 下記のように変更を行えば、正常に登録がされます。 変更前:ps2.setString(1, "20210431"); 変更後:ps2.setString(1, "20210432"); おわりに Javaを用いて、データベース操作を行ってみました。 今回のやり方以外にも手法が存在するようなので、都度、学習していけたらと思います。 参考:Javaコード入門 参考:スッキリわかるJava入門 実践編 第3版
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む