2021年4月23日金曜日
SQL Server のデータ移行方法と特徴について。
オフィス狛 技術部のJoeです。
担当したプロジェクトで、SQL Serverのデータを移行する要件がありました。
データの移行方法を調べてみると色々な方法がありましたので、
いくつかの移行方法と、その特徴をまとめてみました。
1.デタッチとアタッチ
【主な手順】移行元でデタッチ
-> データファイルとトランザクションログファイルを移行先にコピー
-> 移行先でデータファイルをアタッチ
【特徴】
・データファイルとトランザクションログファイル自体を移行します。
(実質、データベースの移行になります)
・デタッチすると、DBが参照できなくなります。
(アタッチし直せば、また参照可能になります)
・SQL Serverのバージョンアップにも対応しています。
・デタッチには、いくつかの制限事項があります。(下記の「データベースのデタッチ」を参照)
https://docs.microsoft.com/ja-jp/sql/relational-databases/databases/database-detach-and-attach-sql-server?view=sql-server-ver15
・後述する移行方法と比較すると、移行に掛かる時間は最も短いです。
2.バックアップとリストア
【主な手順】移行元でバックアップ
-> バックアップファイルを移行先にコピー
-> 移行先でリストア
【特徴】
・バックアップファイルを作成して移行します。
(実質、データベースの移行になります)
・DBを停止しなくても移行可能です。
・SQL Serverのバージョンアップにも対応しています。
・リストアの際に、DBとデータファイル名を変更することで、DB名の変更が可能です。
同じインスタンス内であれば、DB名を変更することで、複製することもできます。
3.ExportとImport
【主な手順】Data Source設定 -> Destination設定
※SQL Server Management Studio の「Import and Export Wizard」を利用した場合です
【特徴】
・移行先から直接移行先へデータを移行可能です。
・DBを停止しなくても移行可能です。
・Destinationに「Flat File Destination」を指定すれば、移行元のデータをファイル化することができます。
ただし、テーブル単位でしかファイルを作成できませんでした。
・「Import and Export Wizard」は機能が多く便利なのですが、逆に使いこなすことが難しいと感じました。
一度、「Import and Export Wizard」でデータ移行を試してみたところ、下記エラーが発生しました。
Error 0xc02020f4: Data Flow Task 1: The column "カラム名" cannot be processed because more than one code page (932 and 1252) are specified for it.こちらは、Import と Export するテーブルの照合順序(Collation)が異なっていたことが原因でしたが、
メッセージから原因が予測できず、解決するのに少し時間が掛かってしましました。
4.スクリプト作成と実行
【主な手順】移行元でスクリプト作成
-> スクリプトコピー
-> 移行先でスクリプト実行
※SQL Server Management Studio の「Generate and Publish Scripts」を利用した場合です
【特徴】
・スクリプトファイルを作成します。
・DBを停止しなくても移行可能です。
・スクリプトファイルは、スキーマのみ(CREATE DATABASE、CREATE TABLE 等)、
データのみ(INSERT)や、スキーマとデータ両方など、用途によって作成できます。
・SQLが直接書かれたファイルなので、大量データの場合はファイル容量が大きくなり、
スクリプトを実行する際も、時間が掛かってしまいます。
・逆に、SQLを直接修正(スキーマの変更や、データの編集)できるので、
データ量が少ない場合は扱い易いです。
データ移行は、移行時のシステムの稼働状態やデータ量などによって、
適切な移行方法を選定する必要がありますので、上記の特徴が何かお役に立てれば幸いです。
2021年3月30日火曜日
Swift・UIBarButtonItemのtitleを変更する。
こんにちは、オフィス狛 技術部のpinoです。
この度、初めてiOSアプリの開発に携わることができました。
まだまだ勉強中の身ですが、今回は「UIBarbuttonItemのtitleを変更する方法」について紹介したいと思います!
方法
早速ですが、UIBarbuttonItemのtitle変更方法です。
private func setBarButtonItem() {
// UIBarbuttonItemのactionを設定
let button = UIBarButtonItem(title: "タイトル", style: .plain, target: self, action: #selector(self.buttonTapped(_:)))
}
@objc func buttonTapped(_ sender: UIBarButtonItem) {
// 変更後のタイトルを設定
sender.title = "変更後のタイトル"
}
タップ時の処理でUIBarButtonItemを引数にとって、
(仮引数名がsenderの場合)sender.title = "hoge"としてあげることでtitleの変更ができます。
...思いのほか、すごく簡単でしたね!
せっかくなので、ここからはこのtitle変更を活かしたものを作ってみたいと思います。
作るもの
以下のようなものを作っていきます。
- ・画面真ん中にTextFieldを配置
- ・TextField押下でキーボード表示。このキーボードの上にUIToolbarを配置
- ・UIToolbar上に並んでいるUIBarButtonItemタップで、キーボードタイプを切り替え
UIBarbuttonItemのtitle変更は、「UIBarButtonItemタップ」で発火するようにしてみます。
準備
Interfaceに「Storyboard」を選択して、プロジェクトを作成します。画面真ん中にTextFieldを置いて、Keyboard Typeを「Number Pad」にしておきます。
ViewControllerで、TextFieldにUIToolbarを追加します。
ViewController.swift
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var sampleTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.setToolbar()
}
private func setToolbar() {
let toolbar = UIToolbar()
toolbar.sizeToFit()
let inputSwitchButton = UIBarButtonItem(title: "英数字入力に切り替え", style: .plain, target: self, action: nil)
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
toolbar.items = [space, inputSwitchButton]
self.sampleTextField.inputAccessoryView = toolbar
}
}
ここまでで、「英数字入力に切り替え」というtitleのUIBarButtonItemが表示されるようになりました。
UIBarbuttonItemのtitle変更
UIBarButtonItemタップ時の処理を定義します。
ViewController.swift
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var sampleTextField: UITextField!
// 中略
private func setToolbar() {
let toolbar = UIToolbar()
toolbar.sizeToFit()
let inputSwitchButton = UIBarButtonItem(title: "英数字入力に切り替え", style: .plain, target: self, action: #selector(self.inputSwitchButtonTapped(_:))) // 🍀変更
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
toolbar.items = [space, inputSwitchButton]
self.sampleTextField.inputAccessoryView = toolbar
}
// 🍀追加
@objc func inputSwitchButtonTapped(_ sender: UIBarButtonItem) {
sender.title = "数字入力に切り替え"
}
}
inputSwitchButtonTapped()を定義して、その中でtitleの変更を行うようにしました。
さらに、inputSwitchButtonの#selectorに
inputSwitchButtonTapped()を設定することで、
ボタンタップ時にtitleが「数字入力に切り替え」へと変更されるようになります。
ここまでで、実際の動きは以下のようになります。
1回タップした後は、特に変化がありませんね。
今回はtitleと一緒にKeyboard Typeも変更したいので、inputSwitchButtonTapped()を以下のように修正します。
@objc func inputSwitchButtonTapped(_ sender: UIBarButtonItem) {
// キーボードが表示されたままだとKeyboard Typeの変更が反映されないのでフォーカスを外す
self.sampleTextField.resignFirstResponder()
// 🍀以下の分岐を追加
if self.sampleTextField.keyboardType == .numberPad {
sender.title = "数字入力に切り替え"
self.sampleTextField.keyboardType = .namePhonePad
} else if self.sampleTextField.keyboardType == .namePhonePad {
sender.title = "英数字入力に切り替え"
self.sampleTextField.keyboardType = .numberPad
}
// Keyboard Typeを切り替えた後に再度フォーカスする
self.sampleTextField.becomeFirstResponder()
}
(フォーカスのつけ外しについては、コメントの通りです)
現在のKeyboard Typeを判定して、titleとKeyboard Typeが切り替わるようにしました。
完成!
完成形は、以下のようになります。
以上、UIBarbuttonItemのtitleを変更する方法について紹介しました。
参考になるとうれしいです。
2021年3月29日月曜日
windows.openを使用した時に、iOSのSafariにて別タブでファイルを開けない場合の対処法。
オフィス狛 技術部のmmm(むー)です。
タイトルの通りですが、windows.open()を使用した際にiOSのSafariにて別タブでファイルを開くことができなかったため、その対処法を書きます。
1. リンクを押下後、APIを呼ぶ
2. API(Express)で、S3にあるPDFデータ(Blob)をレスポンスする
3. フロントにてAPIからのレスポンスを取得した後、別タブを開きPDFを表示する
・PCブラウザ(Chrome、 Firefox、 Sarfari)やiOSブラウザ(Chrome)はリンク押下後に別タブでPDFを開くことができる
observable.subscribe(downloadData => {
const blob = new Blob([downloadData], { type: 'application/pdf' });
const fileURL = window.URL.createObjectURL(blob);
window.open(fileURL, '_blank');
})
this.windowReference = window.open(); // <- 🌟変更
observable.subscribe(downloadData => {
const blob = new Blob([downloadData], { type: 'application/pdf' });
const fileURL = window.URL.createObjectURL(blob);
this.windowReference.location = fileURL; // <- 🌟変更
})
・ただ、別タブで開くか確認するポップアップが表示されますし、デフォルトはONになっています。
設定変更方法:iPhoneの設定 > Safari > ポップアップブロックをOFF
以上となります。
同じようにはまった方の参考になりましたら、幸いです🍭
2021年1月22日金曜日
WindowsでDockerを利用してDynamoDBサーバーをたちあげる時の注意点。
先日「WindowsでDockerを利用してMySQLサーバーを立てる場合の注意点」でも投稿しましたが、WindowsはDockerをVirtualBox経由で起動させているため、Macで起動する場合とは違い、うまく動かない部分があります。
今回は、WindowsでDockerをつかってDynamoDBサーバーをたちあげる時の注意点を記載しようと思います。
※今回DynamoDBはAWSのDynamoDB Localというツールを利用します。
前回投稿した時と同じようにDockerの起動にはdocker-compose.ymlを利用していきます。
docker-compose.ymlには以下のようにDynamoDBの接続設定を記載します。
※今回DBの記述がメインとなるので、API、DB側の記述は割愛します。
version: '3'
services:
api:
build:・・・
・・・
db:
build:・・・
・・・
dynamodb:
image: amazon/dynamodb-local:latest
container_name: elps-client-dynamodb
command: -jar DynamoDBLocal.jar -sharedDb -dbPath . -optimizeDbBeforeStartup
ports:
- "8000:8000"
前回同様上記のように書いて、あとは通常通り上記ymlを使ってDocker起動するだけです。
で、上記方法で、またまたMacでは上手くいくのですが、Windowsではなぜかうまくいきません。
起動はうまくできるのですが、設定したDynamoDBに接続ができないのです。😢
で、またいろいろ調べていくと、やっぱり今回もVirtualBox経由での起動が問題を引き起こしているようでした。。。
今回DynamoDBの接続ポートに8000を指定しているのですが、これはホストマシンのlocalhostで接続しに行きます。
ただ、DockerはVirtualBoxで起動しているため、VirtualBox側の設定でポートフォワーディングが必要なようです。
VirtualBoxのDynamoDBのポートフォワード設定方法
①まずVirtualBoxの「設定」ウィンドウから下記のように「ネットワーク」→「ポートフォワーディング」ボタンを押下します。
②ポートフォワーディングルールの画面の右側の+ボタンを押下して、今回のDynamoDBのポート8000を追加して、「OK」ボタンを押下します。

上記完了後、NoSQL Workbench等のツールや、AWS CLI等を利用してDynamoDBに繋がっているか確認できればOKです。
WindowsユーザーでDockerかつDynamoDBを使う場合には、これ結構ハマりポイントだと思うので、ご参考になれば幸いです。
アピアランスで文字の周りに少し大きい枠線をつくる。
2021年1月8日金曜日
2021年オフィス狛の年賀状の制作秘話。
2020年12月30日水曜日
Angular・Componentのタグにclassを付与したい【HostBinding】
こんにちは、オフィス狛 技術部のpinoです。
早速ですが、皆さんはAngularをやっていて「コンポーネントのタグに直接classを付与したいんだけどなぁ....。」と思った経験はないでしょうか。
今回は、そんな時に使える @HostBinding についてご紹介したいと思います!
準備
まずは、コンポーネントを用意します。app.component.html(親コンポーネント)
<header class="header">
<section class="header__about">
<h1 class="header__title">@HostBinding Sample</h1>
<p class="header__lead">動作確認用のサンプルです</p>
</section>
<nav class="header-nav">
<ul class="header-nav__list">
<app-list-item *ngFor="let name of names" [name]="name"></app-list-item>
</ul>
</nav>
</header>
list-item.component.html
<li class="header-nav__item">
<input type="checkbox" />{{ name }}
</li>
list-item.component.css
.header-nav__item {
width: 120px;
height: 64px;
padding-left: 32px;
line-height: 64px;
}
list-item.component.ts
import { Component, Input, OnInit } from '@angular/core';
@Component({
selector: 'app-list-item',
templateUrl: './list-item.component.html',
styleUrls: ['./list-item.component.scss']
})
export class ListItemComponent implements OnInit {
@Input() name: string;
constructor() { }
ngOnInit(): void {
}
}
ビルド後のイメージ
色味がなく、シンプルで寂しい印象です。
ここから、実際にHostBindingを使ってclassを付与してみたいと思います。
HostBindingの使い方
使い方は1. コンポーネントのタグにclassを付与する
2. 上記1に加えて、動的にclassの付け外しをする
と、主に2つあります。
まずは、1. コンポーネントのタグにclassを付与するについてです。
こちらは、大きく2通りの書き方ができます。
list-item.component.css
import { Component, HostBinding, Input, OnInit } from '@angular/core'; // HostBinding を追加
@Component({
selector: 'app-list-item',
templateUrl: './list-item.component.html',
styleUrls: ['./list-item.component.scss']
})
export class ListItemComponent implements OnInit {
@HostBinding('class') listItem = 'list-item'; // ①
@HostBinding('class.first') first = true; // ②
@Input() name: string;
constructor() { }
ngOnInit(): void {
}
}
ポイントは、@HostBinding()の、()の中です。
①は、「'class'」のみ指定して、なんのclassを付与するかは変数の値が使用されるパターンです。
値部分に定数を使えば、ロジック側にテンプレートの情報をベタ書きすることも避けられますね。
固定のclassであればこれで十分そうです。
②は、「'class.first'」と付与するclass名まで指定するパターンです。
この場合は、後に続いている値がtrueであれば付与、falseであれば付与しない、ということになります。
(※真偽値を固定で設定したい場合は、「@HostBinding('class.first') readonly first = true;」 といった具合に、readonlyをつけるなどの対策が考えられます。)
また、HostBindingの話とはすこし逸れますが、コンポーネントのタグに使用するclassは
グローバルである(style.cssに記述されている等)か、:hostメタデータを使用する必要があります。
今回は、自コンポーネントのCSSに背景色をつけるclassを用意したいと思います。
list-item.component.css
// 以下を追加
:host.list-item.first {
background-color: #7ae5ec;
}
:host.list-item.second {
background-color: #7aecc0;
}
:host.list-item.third {
background-color: #7ab9ec;
}
ここまでのビルド後イメージ
すべてのコンポーネントにclassが付与されて、背景色がつきました。
次は、2. 上記1に加えて、動的にclassの付け外しをするについてです。
list-item.component.css
export class ListItemComponent implements OnInit {
@HostBinding('class')
@Input() name: string; // ①
// 今回formは用意していないので、例としてだけ挙げます
@HostBinding('class.valid') get valid() {
return this.form.valid;
} // ②
@HostBinding('class.list-item') isClick = false; // ③-A
...
onClick(): void {
this.isClick = !this.isClick;
} // ③-B
他にもいろいろな方法があると思うのですが、簡単に思いつくものを挙げてみました。
①は、Input()で受け取った値を使用します。
組み合わせて使うだけで、特別なことをしてる感じがします...!
②について、今回Formは用意していないので記述の例になるのですが、状態など値そのものを監視したい時に使える方法です。
getterってあまり使う機会がなかったのですが、今回試してみたところ使い勝手がいいですね!
また③は、②のようにイベント発生時ではなく、識別子に設定した変数の値を書き換えることによってclassの付け外しをしています。
ここまでで、上記の①と③をプログラムに落とし込んだビルド後のイメージが以下のようになります。
それぞれで別々のclassの付与と、classの付け替えができました!
補足
ここまでclassを付与する使い方を紹介してきましたが、なんとHostBindingはclass以外のバインディングにも使えます。例えば、「@HostBinding('style.display') flex = 'flex';」としてあげればstyle="display: flex;"がバインドされます。
便利!
今回は公式以外に以下サイトも参考にしたのですが、「HostBinding('value') myValue;は[value]="myValue"と全く同じです。」という一文が特にわかりやすかったです。
@HostBindingと@HostListener:彼らは何をし、何のためにいますか?
以上、HostBindingデコレータについて紹介しました。
参考になればうれしいです。

























