okinawa

IT勉強メモ

【.Net Core5】DBファーストでモデルクラス作成からCRUD機能の作成までの流れ

参考サイト

https://mebee.info/2021/02/14/post-28952/  

手順0:DBの作成

テーブル作って、外部キーやら自動採番やらの設定をする。

SSMSでの自動採番の設定はテーブル右クリック→デザイン→列名クリック→列のプロパティでIDENTITYの指定を「はい」にする。

外部キーは列名を右クリックでリレーションシップから。

手順1:SQLサーバとの接続

ここからの操作は全部VisualStudio。

1,ツール→データベースへの接続→MicrosoftSQLServer→続行

2,サーバー名とデータベース名を入力→テスト接続

サーバー名とデータベース名はSSMSでデータベースを右クリック→接続のプロパティで見れる。

3,サーバーエクスプローラを開いて接続したDBを右クリック→プロパティで接続文字列をメモっておく。

手順2:スキャフォールディング

1,Nugetでパッケージインストール

2,プロジェクトを1回ビルドする。

3,dotnetをインストール

PMCでもパワーシェルでもどっちでも良い。

dotnet tool install --global dotnet-ef

4,パワーシェルでscafoldコマンド実行。

プロジェクト名を右クリック→ターミナルで開く、でプロジェクトディレクトリのパワーシェルが開く。

dotnet ef dbcontext scaffold "接続文字列" Microsoft.EntityFrameworkCore.SqlServer -o Models

  接続文字列の調べ方↓

dodosu.hatenablog.jp

5,Modelsフォルダの中身確認

モデルクラスとコンテキストクラスが出来てたら成功。

6,Controllersとビューの作成

Controllersフォルダ右クリック→追加→コントローラ

→EntityFrameworkを使用したビューがあるMVCコントローラ

→先程作成した、モデルクラスとコンテキストを選択する。

→追加。まだ終わりではないのです。

手順3:Startup.csとappsettings.jsonとコンテキストクラスに追記。

1,Startup.csに追記

なぜか依存性の注入がされないので追記。

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();

            // 追記部分。
            services.AddDbContext<TestDBContext>(Options => Options.UseSqlServer(Configuration.GetConnectionString("TestDBContext")));

        }

2,appsettings.jsonに追記。

こちらもなぜか接続文字列が定義されないので追記。

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  // 以下、追記部分
  "ConnectionStrings": {
    "TestDBContext": "接続文字列"
  }
}

3,コンテキストクラスに追記。

なぜか主キーが設定されないので追記。

           modelBuilder.Entity<Account>(entity =>
            {
                entity.ToTable("account");

                // 主キーの指定
                entity.HasKey(e => e.AccountId);

                entity.Property(e => e.AccountId).HasColumnName("account_id");
          }

docs.microsoft.com

C# .net Coreの基本

 

参考書籍

この作者さんの本にも大変お世話になっております。

wings.msn.to

 

 コードファーストでDBアクセス

(非スキャフォールディング)モデル作成→DB反映→コントローラからDBアクセスまでの流れ

 

・プロジェクト作成

プロジェクトの作成でASP.NET Core Web アプリ(Model-View-Controller)」を選ぼう!
ASP.NET Core Web アプリ」という似たのがあるので注意!!!
 
次に
EntityFrameworkCore
EntityFrameworkCore.SqlServer
EntityFrameworkCore.SqlServer.Design(DBファーストの時のみ)
EntityFrameworkCore.Tools
Web.CodeGeneration.Design(スキャルフォールディングの時に要求される)
をNuGetする。
 

・モデルクラス作成

モデルクラス作る。
ルールは下記。
・クラス名はテーブル名と同名であること
・プロパティは対応するテーブル列と同盟であること
・主キーはId、もしくはクラス名+Id。(AccountくらすならAccountId)
namespace WebApplication2.Models
{
public class Account
{
public int Id { get; set; }
public int age { get; set; }
public string name { get; set; }
public string email { get; set; }
public string password { get; set; }
 
}
}
 

・コンテキストクラス作成

コンテキストクラス作る。
モデルクラスをDBに橋渡しする役割。
using Microsoft.EntityFrameworkCore;
namespace WebApplication2.Models
{
//DbContextの継承
public class MyContext:DbContext
{
// コンストラク
public MyContext(DbContextOptions<MyContext> options) : base(options) { }
//モデルクラスへのアクセサー
public DbSet<Account> Account { get; set; }
}
}
 
 

・DB接続文字列を定義する

appsettings.jsonにて定義。
"ConnectionStrings": { "接続名": "Server=サーバー名;Database=DB名~"}
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MyContext": "Server=(localdb)\mssqllocaldb;Database=WebApplication2(←プロジェクト名);Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
 

・アプリにコンテキストクラスを登録する

Startup.cs
接続文字列とコンテキストクラスを紐付けする。
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddControllersWithViews();
//コンテキストクラスを登録
services.AddDbContext<MyContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MyContext")));
}
 

マイグレーションを実行する

マイグレーションはモデルクラスを元にDBを作成・変更する仕組み。
ここでは、DBの作成をしている。
ツール→NuGetパッケージマネージャ→パッケージマネージャコンソール
Add-Migration Initial(マイグレーションを追加)
Update-Database (DBに反映)
※注意
表示→SQL Serverオブジェクトエクスプローラーで確認。
なかなか反映されない時はVisualStudioを再起動。
 
rootディレクトリの下にMigrationsディレクトリができる。
これ見ると何やってるかなんとなくわかりそう↓
using Microsoft.EntityFrameworkCore.Migrations;
namespace WebApplication2.Migrations
{
public partial class Initial : Migration
{
//upメソッドでテーブル作成
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Account",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
age = table.Column<int>(type: "int", nullable: false),
name = table.Column<string>(type: "nvarchar(max)", nullable: true),
email = table.Column<string>(type: "nvarchar(max)", nullable: true),
password = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Account", x => x.Id);
});
}
//Downメソッドでテーブル削除
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Account");
}
}
}
 

・コントローラーにコンテキストを注入

using Microsoft.AspNetCore.Mvc;
using WebApplication5.Models;
namespace WebApplication5.Controllers
{
public class HelloWorldController : Controller
{
 
private readonly MyContext _context;
//コンストラク
//依存性の注入でコンテキストクラスを取得
public HelloWorldController(MyContext context)
{
this._context = context;
}
//アカウント情報をビューに渡す
public IActionResult List()
{
return View(this._context.Account);
}
}
}
 

・画面の作成

上記コードのListにカーソルを合わせて右クリック
→ビューの追加
→Razorビュー
→ビュー名List・テンプレートEmpty・レイアウトページを使用するにチェック
→追加でこんなんができる↓
List.cshtml
@{
ViewData["Title"] = "List";
}
<h1>List</h1>
↓コードを追加
<!--Accountモデルを宣言-->
@model IEnumerable<WebApplication5.Models.Account>
@{
ViewData["Title"] = "List";
}
<h1>List</h1>
<h2>アカウント情報</h2>
@foreach (var item in Model)
{
<p>@item.Id</p>
<p>@item.age</p>
<p>@item.email</p>
<p>@item.password</p>
}
 

(有スキャフォールディング)モデル作成→DB反映→コントローラからDBアクセスまでの流れ

モデルクラス作成(非スキャフォールディングと同じ)
スキャフォールディング
Controllersフォルダを右クリック
→追加→コントローラー
→EntityFrameworkを使用したビューがあるMVCコントローラ
→モデルクラス選択&データコンテキストクラスの+ボタンクリック
→ビューの生成・スクリプトライブラリの参照・レイアウトページを使用するにチェック
→追加
 
・生成ファイル
  • ~Controller.cs:CRUD機能が入ったコントローラ
  • Index.cshtml:一覧画面のテンプレート
  • Details.cshtml:詳細画面テンプレート
  • Create.cshtml
  • Delete.cshtml
  • Edit.cshtml
  • ~Context.cs:DBとの橋渡し役のコンテキストクラス
  • 接続文字列の定義(appsetteings.json)
  • コンテキストの登録(Startup.cs)
 
これでコンテキストクラス作成・DB接続文字列の定義・コンテキストのアプリへの登録も全部やってくれる!
恐ろしい!
最後にマイグレーション。パッケージマネージャコンソールで。
Add-Migration Initial(マイグレーションを追加)
Update-Database (DBに反映)
 

 

リクエスト送信→受け取り

cshtmlからリクエスト送信

・リンク
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a>
<a asp-action="Details" asp-route-id="@item.Id">Details</a>
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
<a asp-action="Delete" asp-route-id="@item.Id">Create</a>
・form
<form asp-action="Create" method="post">
 <input type="text" asp-for="Company">
 asp-for="Company"にするとidとnameがCompanyになる。

コントローラでリクエスト受け取り

アクションメソッド名を同じにするだけ。
public async Task<IActionResult> Edit(int? id){ 処理 }
public async Task<IActionResult> Detail(int? id){  }
public async Task<IActionResult> Delete(int? id){  }
public async Task<IActionResult> Create(int? id){  }
 
formからの受け取り
public async Task<IActionResult> Create(Model company){  }
 引数名をasp-for(name属性)と同じにすると受け取れる。

DBでCRUD操作

検索形

Select
・結果が複数の場合
        // GET: Books/Edit/5
        public async Task<IActionResult> Edit(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }
 
            var book = await _context.Book.FindAsync(id);
            if (book == null)
            {
                return NotFound();
            }
            return View(book);
        }
 
・結果が1つの場合
        // GET: Books/Details/5
        public async Task<IActionResult> Details(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }
 
            var book = await _context.Book
                .FirstOrDefaultAsync(m => m.Id == id); //複数と1つでここが違う
            if (book == null)
            {
                return NotFound();
            }
 
            return View(book);
        }
 

検索条件を複数にする

・FirstOrDefaultAsync(m=>条件式 && 条件式 || 条件式)
条件に合致するデータを1件だけ返す。(複数ヒットしても1件)
mは検索対象のモデル。
FirstOrDefaultAsync(m.Id=>id == id && m.name == name);
 

更新系

更新系の場合は引数をBind()でモデルバインディングするのがポイント。
オーバーポスティング攻撃対策。
 
※モデルバインドとは
その名の通り、モデルクラスにバインド(紐付け)すること。
多分もっと広い用途があるので要調査。
 
Insert文(新規作成)
public async Task<IActionResult> Create([Bind("Id,Title,Price,Publisher,Sample")] Book book)
{
if (ModelState.IsValid)
{
_context.Add(book); // ここでInsert
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
//return RedirectToAction("Index");
}
return View(book);
}
Update文
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Edit(int id, [Bind("Id,Title,Price,Publisher,Sample,RowVersion")] Book book)
        {
中略
                try
                {
                    _context.Update(book); //ここでアップデート
                    await _context.SaveChangesAsync();
                }
 
Delete文
        // POST: Books/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> DeleteConfirmed(int id)
        {
            var book = await _context.Book.FindAsync(id);
            _context.Book.Remove(book); //ここでDELETE
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }

 

 

コントローラのアレコレ

コントローラーからテンプレートの呼び出す時の挙動

return View();
上記のようにパス指定なしでテンプレートを呼び出すと、以下のようにアクションに対応したテンプレートを呼び出そうとします。
/Views/コントローラー名/アクション名.cshtml
 
こんな感じで引数指定すれば同コントローラ内の別アクションメソッドを指定できる。
return View("Hoge");
/Views/コントローラー名/Hoge.cshtml
 

別のコントローラのアクションメソッドを呼びたい時はRedirect

・Redirect(string url)
url:URLをパス指定する。多分Viewsがルートディレクトリ。
 
・RedirectToPage(string pageName)
pageName:cshtmlのファイル名の拡張子が無い名称。
 
・RedirectToAction(String actionName [,string controllerName] [,object Values])
  • actionName:アクションメソッド名
  • controllerName:コントローラ名
  • Values:ルートパラメータ
 
 

モデルクラスでできること色々

表示名とデータ型と検証属性の指定。データ型は指定する効果がよくわからず。
[DisplayName("値段")] //ビューでの表示名を付与
[DataType(DataType.Currency)] //ビューでのデータ型を指定。
[StringLength(20, ErrorMessage = "{0}は{1}文字以内で入力してください。")] //検証属性
String price {get; set;}
 
参考

セッション

・参考サイト
 
 
 
 
Startup.csでセッションの設定をする
public void ConfigureServices(IServiceCollection services)
{
 
//セッションの設定
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromSeconds(10);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
}
 
public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
//セッションを使う
app.UseSession();
}
 
セッションを使う
// セッションへ値をセット
HttpContext.Session.SetString("key","value");
HttpContext.Session.SetInt32("key2",123);
 
// セッション変数から値を取得
string mystring = HttpContext.Session.GetString("key");
int myint = HttpContext.Session.GetInt32("key2");
 
セッションをビューで表示
@using Microsoft.AspNetCore.Http
 
<div>
<p>@Context.Session.GetString("test")</p>
</div>
 

同時実行制御(トランザクション的なの)

RowVersionというのを使う。
 

コードファーストで同時実行制御

1,モデルクラスにRowVersion列を追加。
[Timestamp]
public byte RowVersion { get; set; }
 
2,Add-Migration→Update-Database
 
3,Edit.cshtmlにRowVersionを追加。
<input type="hidden" asp-for="RowVersion" />
 
4,Controllerで競合検出
if (ModelState.IsValid)
{
try
{
_context.Update(hoge);
await _context.SaveChangesAsync();
 
}
catch (DbUpdateConcurrencyException)
{
 
//ここ↓
ModelState.AddModelError(string.Empty, "競合が検出されました。");
return View(hoge);
}
return ~;
}
 

DBファーストで同時実行制御

SSMSでrowversionを追加。
 
ただし、GUIだとデータ型でrowversion型が存在しない。
 
なのでSQLで打ち込む。
ALTER TABLE tableName ADD
columnName rowversion NULL;
 
 ちなみに上記SQLを打っても、GUI上だとTimestamp型と表示されるが実際にはrowversion型らしい。
 
あとの手順はコードファーストとほぼ一緒。Add-Migration→Update-DatabaseはやらなくてOK。
 
参考サイト

social.msdn.microsoft.com

 

コードファーストで主キーの名前を変える方法

コードファーストだと主キー名が「Id」か「classNameId」しかつけられない。
Companyクラスなら「Id」か「CompanyId」
 
・参考
 
・コンテキストクラスを変更する。
public DbSet<Test> Test { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Test>()
.HasKey(b => b.Test_id) //←こっちがモデルクラスの名前
.HasName("Test_id"); // ←こっちがDBのカラム名
}
 

VisualStudio内のDBで主キー名変更の場合

主キー名を変える場合は一度DBごと消さないとダメ。
手順は
上記の要領でコンテキストクラス変更
→DBを消す
マイグレーションファイルも消す
→Add-Migration
→Update-Database
 

入力チェック(バリデーション)

モデルクラスに検証属性を付与。
[StringLength(20, ErrorMessage = "{0}は{1}文字以内で入力してください。")]
public string TeamName { get; set; }
 
ビューでエラメッセージを表示。
asp-validation-summary="ModelOnly":モデル全体に関わるエラーだけを表示する。
asp-validation-for="CharacterName":CharacterNameに関するエラーを表示。
Hoge.cshtml
<div asp-validation-summary="ModelOnly" class="text-danger"></div> //ModelOnlyはモデル全体に関わるエラーだけを表示する。
<span asp-validation-for="CharacterName" class="text-danger"></span> //CharacterNameに関するエラーを表示。
 
//入力チェックのためのJavaScriptライブラリのインポート。
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
 
・参考
 

ルーティング

pattern:”{controller}/{action}/{id}”
  • {controller}にはコントローラ名
    • {controller=Home}の「=」はこのパラメータの既定値をHomeにする。
  • {action}にはメソッド名(アクションメソッド)
    • {action=Index}の「=」はこのパラメータの既定値をIndexにする。
  • {id}にはメソッドに渡す値
    • /{id?}の「?」はこのパラメータを省略可にする。
 
Startup.cs
```
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
```
 

Razor

Razorテンプレートによる変数出力・処理の実行の基本

・サーバー側
ViewBag.変数名=値
ViewData[“変数名”]=値
 
```
public IActionResult Greet()
{
ViewBag.Message = "こんにちは、世界!";
 
return View();
}
 
```
 
・画面側
@・・・は出力。
@{・・・}はコードブロック。実行。出力するわけではない。
 
@{
ViewData["Title"] = "Greet";
}
 
<h1>Greet</h1>
<p>@ViewBag.Message</p>
 

Razor側でモデルクラスをインポート・取り出し

<!- Bookモデルを参照する></!->
@model IEnumerable<QuickMaster.Models.Book>
 
// 取り出し
@foreach (var item in Model)
{
<tr>
<td>@item.Title</td>
<td>@item.Price</td>
<td>@item.Publisher</td>
<td>@item.Sample</td>
</tr>
}
 

ヘルパーメソッド一覧

  • ViewResult View():テンプレートに基づいてページ出力
  • ContentResutl Content(string content):テキスト出力
  • RedirectResult Redirect(string url):指定されたパスに移動(リダイレクト)
  • RedairectToAction() 指定されたアクションに移動(リダイレクト)
  • File():指定されたバイト配列をファイルとして出力
  • NotFound();404エラーを出力
 

よく使うビューヘルパー/タグヘルパー一覧

ビューヘルパー一覧
  • @foreach
  • @Html.Displayfor データ方に応じて出力を変化させる。
  • @Html.DisplayNamefor プロパティ名↓を表示する。列名のタイトル表示に使う。
 
タグヘルパー一覧
<form asp-controller="">:コントローラ名に関連づいたフォーム
<form asp-action="">:アクション名に関連づいたフォーム
<a asp-controller="">:コントローラ名に関連づいたリンク
<input asp-for="">:入力タグヘルパー 例:asp-for="company"にするとid="company" name="company"になる。
<select asp-for"">:セレクトボックス
<textarea asp-for="">:テキストエリア
<label asp-for="">:ラベル
<span asp-valication-for="">:入力エラー。個別のプロパティ
<div asp-validation-summary="">入威力エラー。モデル全体。
 
公式:組み込みタグヘルパー一覧↓
 
ASP.NET Core MVC の Razor で使える Tag Helpers のメモ書き
 

動的なSelectボックスの使い方

・参考サイト
 
サーバ側でセレクトボックスに渡す値を用意。
SelectList()を使う。
--------------------------
SelectList(IEnumerable items, string dataValueField, string dataTextField, object selectedValue)
items:列挙可能なもの。コレクションとかDBの検索結果をそのままぶち込める。
dataValueField:valueに入る値。
dataTextField:画面に表示される値。
selectedValue;初期値。
-------------------------
// 画面にはTeamNameが表示されるが、valueにはTeamIdが入る。
ViewData["TeamId"] = new SelectList(_context.Teams, "TeamId", "TeamName", character.TeamId);
return View(character);
 
ビューでセレクトボックスを表示。
<select asp-for="TeamId" class="form-control" asp-items="ViewBag.TeamId"></select>
 

部分ビュー

Sharedディレクトリに_bubunView.cshtmlを作成。
@using Microsoft.AspNetCore.Http
<div>
<p>@Context.Session.GetString("test")</p>
</div>
 
cshtmlに表示。
<h1>Create</h1>
<partial name="_bubunView" />
<h4>Team</h4>
 

VisualStudioでのSQL Serverの接続文字列の確認方法

・最初にメモっておく方法
SQL Serverをインストールした時に1回だけ表示されるのでメモっておく。

 

・あとから調べる方法
zebratch.blog.ss-blog.jp

 

まずサーバー名を調べる。
SQL Server Management Studioでデータベース右クリック→プロパティ→接続のプロパティの表示で見れる。
サーバー名が自分のPC名になってたら接続文字列のサーバー名はlocalhostにする。

 

次にvisual studioでデータベース接続をする。
visual studio2019ではツール→データベースへの接続で、サーバー名とデータベース名の入力だけでOK。
接続できたらDBを右クリック→プロパティで接続文字列を見れる。

 

私の環境では下記。

上が最初にメモっておいたやつ。下が後から調べたやつ

Server=localhost\SQLEXPRESS;Database=DB名;Trusted_Connection=True;
Data Source=localhost\SQLEXPRESS;Initial Catalog=DB名;Integrated Security=True;

 

もっと簡単な方法ないのかな?

非同期処理とマルチスレッドの違い

 

結論

同期処理と非同期処理の違い=待つか待たないか。
シングルスレッドとマルチスレッドの違い=単線か複線か。

 

同期処理

今の処理が終わるまで待つ。

次の処理は始まらない。

 

非同期処理

今の処理で待ち時間ができたら、次の処理を始める。

同時に実行しているわけではなく、待ってる間に次を始める

 

AさんがBさんに仕事を渡す

→Bさん仕事中

→AさんはBさんの仕事が終了するまで進められない

→Aさんは別の仕事を見つけてやり始める

 

ぼーーっとするくらいなら次にいこうねって感じ。

シングルスレッドで実装可能。

これが非同期処理。

 

シングルスレッド

同時実行不可。

 

マルチスレッド

同時実行可能。

 

キューとは

 順番待ち行列のこと。

1個ずつ処理されていく。

 

非同期処理の例

JavaScriptとHTTP

JavaScriptでHTTPにリクエスト送った。

HTTPからレスポンス返ってくるまで暇。

じゃあJavaScriptは別のことやるか。

HTTPから完了通知来たらキューに入れよ。

 

・CPUとプリンタ

CPUは高速だがプリンタは低速。

CPUからプリンタに指令を出した後、CPUはやることがない。

だから次の処理に移行する。

プリンタからの完了通知は割り込み信号によって検知する。

信号きたらキューに入る。

 

okwave.jp

setTimeoutは勘違いしやすい

function doSample() {
setTimeout(onFirst, 2000);
setTimeout(onSecond, 4000);
 
function onFirst() {
console.log("first")
}
 
function onSecond() {
console.log("second")
}
}
doSample();

上記コードは合計4秒で完了する。

シングルスレッドなら2+4で合計6秒じゃないの?と思っていた。

 

だけど、setTimeoutはx秒後に処理を始めるという登録をするだけ。

なので処理は一瞬で完了するんだって。

 

seTimeout1実行→setTimeout2実行→2秒後に完了通知→4秒後に完了通知

ということ。

teratail.com

setTimeoutの疑問

待ち時間をカウントして完了通知を送る、という処理はJavaScriptではない何かがやっているということになる。

一体それはなんだろう?

 

参考↓

coliss.com

上記サイトによるとsetTimeoutは指定秒後に実行ではなく、指定秒後にキューに送るということらしい。

また、待ち時間のカウントはWebAPIがやっているらしい。

 

非同期処理で勘違いしていたところ

HTTPレスポンスが返ってくるまで別の処理をやる、みたいなのが多くて、これってリクエスト送る→レスポンス受け取るっていう処理と別の処理を同時にやっているんだからマルチスレッドじゃないか!みたいに思っていたがそんなことはなかった。

 

レスポンスを返してくるのはHTTPのお仕事であってJavaScriptではないので、その間にJavaScriptは別のことを1つやっているだけだよね。

 

JavaScriptでは必ず同期処理の完了後に非同期処理が完了するのはなぜか?

ここちゃんと調べてないので私の予想です。
同期処理1
非同期処理1
非同期処理2
同期処理1
----------
結果
同期処理1完了
同期処理2完了
非同期処理1完了
非同期処理2完了
--------
これは
  1. 同期処理1が開始&完了
  2. 非同期処理1が開始
  3. 非同期処理1完了後の処理1がキューに入る
  4. 非同期処理2が開始
  5. 非同期処理2完了後の処理2がキューに入る
  6. 同期処理2が開始&完了
  7. 非同期処理1の完了通知&完了
  8. 非同期処理2の完了通知&完了
ということなんじゃないかなと思う。
ちなみに最後の非同期処理1・2の完了は順不同です。
完了通知が来た順に完了するので。
 
コードにするとこう↓
console.log(1);
setTimeout(first,1000);
setTimeout(second,500);
console.log(2);
 
function first() {
console.log("first");
}
 
function second() {
console.log("second");
}
-------------
1
2
second
first
-------------

DB・SQLの基本

 

参考図書

・スッキリわかるSQL入門
スッキリシリーズは本当に素晴らしい。
いつおもお世話になっております。
 

select

検索
select 列名 from table名;
 

select文全部入り

select文に全構文を入れるとこうなる。
select 列名
from table
where 条件式
group by 列名
having 条件式
order by 列名
 

insert

挿入・新しい行の作成
insert into teble名 (列名, 列名, 列名) values('値', '値', '値');
 
全列追加なら列名省略できる
insert into teble名 values('値', '値', '値');
 

update

更新・すでにある行の修正
update table名 set 列名 = '値' where 列名 = '値';
where句なしだと全行更新になる。
 

delete

削除・行の削除
delete from table名 where 列名 = '値';
where句なしだと全行更新になる。
 

演算子

比較演算子

=, <, >, <=, >=, <>

<>は左右の値が等しくない

!=と同じ
select * from 家計簿 where 出金額 <> 1000;
 

Null判定

=で判定できない。
式 is nll;
式 is not null;
select * from 家計簿 where 出金額 is null;
select * from 家計簿 where 出金額 is not null;
 

LIKE

select * from table where A LIKE '%abc%';
 

BETWEEN

ある範囲内に値がおさまっているかを判定。
式 BETWEEN 値1 AND 値2;
select * from table where 出金額 between 100 and 300;
 

IN/NOT IN

値がカッコ内の複数の値のいずれかに合致するかを判定する。
式 IN (値1, 値2, 値3)
select * from table where 出金額 in (100, 299, 300);
select * from table where 出金額 not in (100, 299, 300);
 

ANY/ALL

ANYは値リストと比較して、いずれかが真なら真
ALLは値リストと比較して、全てが真なら真
式 比較演算子 ANY  (値1, 値2, 値3)
式 比較演算子 ALL  (値1, 値2, 値3)
select * from table where 出金額 < ANY (100, 200, 300);
select * from table where 出金額 > ALL (100, 200, 300);
 

AND/OR

条件式 AND 条件式
条件式 OR 条件式
select * from table 出金額 < 100 AND 出金額 > 50;
select * from table 出金額 = 100 OR 出金額 = 50;
 

論理演算子の優先順位

NOT>AND>ORの優先順位
 
例:下記は、条件式2 AND 条件式3をまず評価
→その結果と条件式1 OR 条件式4を評価する。
SELECT * FROM 湊くんの買い物リスト
WHERE 販売店 = 'A' /* 条件式1 */
OR 販売店 = 'B' /* 条件式2 */
AND カテゴリ = 'ゲーム' /* 条件式3 */
OR カテゴリ = 'DVD' /* 条件式4 */
多分こうなってる→(販売店B AND ゲーム)OR 販売店A OR DVD
 
カッコで括ると優先順位を変えれる
SELECT * FROM 湊くんの買い物リスト
WHERE ( 販売店 = 'A' OR 販売店 = 'B')
AND ( カテゴリ = 'ゲーム' OR カテゴリ = 'DVD');
 

主キー

必ず何らかのデータが格納される。NOT NULL
他の行と重複しない。
 

複数列を主キーにする

例:氏名と生年月日を主キーにする
氏名だけだと重複するが、生年月日も含めれば重複しない。
 

検索結果を加工する

DISTINCT

重複行を除外する。
複数列指定の場合は全ての列の値が重複している場合のみ除外。
select distinct 列名 from table;
select distinct 列名1, 列名2 from table;//全ての列の値が重複している場合のみ。
 

ORDER BY

並び替え
ASC昇順
DESC降順
select column FROM table ORDER BY 出金額 DESC;
 
複数行指定での並び替え
最初に指定された列でまず並び替え、同じ値があれば次の指定で並び替え。
select column from table ORDER BY 入金額 DESC, 出金額 ASC;
※注意
並べ替えはDBに結構な負荷がかかる。
インデックスの併用を推奨。
DISTINCTとUNIONも並べ替えを行っていることがある。
 

LIMIT/OFFSET

先頭から数行だけ取得する。
LIMIT 取得行数 (OFFSET 先頭から除外する行数)
select * from table LIMIT 10;
select * from table OFFSET 20;
select * from table LIMIT 10 OFFSET 20; // 先頭20行を除き、21行目から30行目までを取得。
 

集合演算子

集合演算子が使える条件:
列数とデータ型が一致している事。
上記が一致していれば違うテーブルや列でもOK。

UNION

和集合

2つの検索結果を足し合わせたもの。
select 文1
UNION (ALL)
select 文2
デフォルトだとUNIONは重複行をまとめる。
UNION ALLにすると重複行も全てそのまま返す。
ちなみに列の数が同じテーブル同士じゃないとUNIONできない。

UNIONとJOINの違い

UNIONは行を足す。テーブルが下に伸びる。

JOINは列を足す。下にも横にも伸びる。

列は、tableA + tableB
行は、tableA × tableB

になる。

詳しくは下記を参考に。

テーブル結合ってなんなの?

 

EXCEPT/MINUS

参考:SQL EXCEPTのサンプル(差分を抽出する)↓
 
差集合。ある集合と別の集合の差。

あるセレクト文の検索結果に存在する行から、別のセレクト文の検索結果に存在する行を差し引いた集合。
select 文1
EXCEPT(ALL)
SELECT 文2
 
下記はテーブルAで取得した行とテーブルBで取得した行を全ての列の値で比較し、列の値がすべて一致する行は抽出しません。
→テーブルAのみにある行を抽出します。
select * from テーブルA
EXCEPT
select * from テーブルB
 
順番にも注意。
下記はテーブルBのみにある行を抽出します。
select * from テーブルB
EXCEPT
select * from テーブルA
 
※注意
OracleではEXCEPT使えず、MINUSを使う。
MySQLはどっちも使えない。
 

INTERSECT

積集合を求める。

2つのセレクト文に共通する行を集めた集合です。
select 文1
INTERSECT
select 文2
 

式と関数

式の種類

足し算
数値+数値・日付+数値
引き算
数値ー数値・日付ー日付
掛け算
数値*数値
/
割り算
数値/数値
|| or +
文字列の連結
文字列||文字列
 

select文で存在しない列を表示する

出金額, 出金額+200, 固定値という3つの列が表示される。
select 出金額, 出金額+200, '固定値'
from 家計簿;
 
出金額、200円増しの2つの列が表示。中身は200円増しの値。
select 出金額, 出金額+200 as 200円増し
from 家計簿;
 

CASE演算子

if文と同じ。
CASE 列や式 WHEN 値 THEN 値
WHEN 値 THEN 値 //elseif
ELSE 値 // else
END AS 列名
 
単純case式
=判定しかできない。
CASE gender
WHEN '男' THEN 1
WHEN '女' THEN 2
ELSE 99
END
 
検索case式
CASEの後にすぐWHENを書く。
=以外の比較演算子も使える。
CASE WHEN 入金額 < 5000 THEN 'お小遣い'
WHEN 入金額 < 100000 THEN '一時収入'
WHEN 入金額 < 300000 THEN '給料出たー!'
ELSE '想定外の収入です!'
END AS 収入の分類
 

関数

例:length関数
文字列の長さを表す。
LENGTH(引数)
SELECT メモ, LENGTH(メモ) AS メモの長さ
FROM 家計簿
 

ストアドプロシージャ

データベース世界における戻り値のない関数。

ストアドファンクション

データベース世界における戻り値のある関数。
 
参考:わかりそうでわからないストアドプロシージャ
 

よくある関数

length/len 文字列の長さ
trim/Ltrim/Rtrim 前後/左/右の空白除去
replace 指定文字置換
substring/substr 文字列の一部抽出
round 指定ケタで四捨五入
power べき乗
current_date/current_time 現在の日付/時刻
cast データ型変換
coalesce 最初に登場するNULLでない値を返す
 

関数の小技

「select 関数」で関数の動作を確認。
select length('あああ');// 表示結果は3
 

集計関数とグループ化

SELECT文でしか使えない
  • select文の選択列リスト部分○
  • having句の中○
  • where句の中×
集計関数の結果は必ず1行になる。
結果表がデコボコになる形はダメ(各列の行数が同じじゃないとダメ)
 

集計関数の種類

SUM

全行の値を足す。
数値。
NULLは無視。

max

各行の最大値を求める。
数値・文字列・日付。
NULLは無視。

min

最小値。
数値・文字列・日付。
NULLは無視。

avg

平均値。
数値。
NULLは無視。

count

行数をカウントする。
count(*)// NULLを含めて行数をカウント
count(列) // NULLを無視してカウント
count(distinct 列名) // 重複行を除いたカウント
 

グループ化

GROUP BY

GROUP BY 列名
 
SELECT 費目, SUM(出金額) AS 費目別の出金額合計
FROM 家計簿
GROUP BY 費目 --費目列でグループ化する
 

GROUP BYを増やすと分割されていく

SELECT 費目, 性別, SUM(出金額) AS 費目別の出金額合計
FROM 家計簿
GROUP BY 費目, 性別 --費目列でグループ化する
 
SUM(出金額)
↓費目列を追加
 
SUM(出金額)→ 費目1のSUM(出金額)
       → 費目2のSUM(出金額)
↓ 性別列を追加
 
SUM(出金額)→ 費目1のSUM(出金額)→費目1の性別:女のSUM(出金額)
                    →費目1の性別:男のSUM(出金額)
 
       → 費目2のSUM(出金額)→費目1の性別:女のSUM(出金額)
                    →費目1の性別:男のSUM(出金額)
 
こんな感じでどんどん枝分かれしていくイメージ。  
1本の枝が2本、4本、8本と2の2乗で枝分かれしていく。
 

HAVING

集計後・グループ化後に絞り込む。
SELECT 費目, SUM(出金額) AS 費目別の出金額の合計
FROM 家計簿
GROUP BY 費目
HAVING SUM(出金額) > 0 --合計値が0 より大きいグループを抽出
whereとやってることは同じ。
whereは集計・グループ化前に絞り込み。
havingは集計・グループ化後に絞り込み。
 

副問い合わせ

ほかのSQL文の一部分として登場するSELECT文。
SELECT 列名 FROM table
WHERE 列名 = (SELECT MAX(金額) FROM table2)
 

副問い合わせ処理のしくみ

副問い合わせ⇒主問い合わせの順に処理される。
副問い合わせの中に副問い合わせも書ける。
 

副問い合わせのパターン

得られる結果はこの3つ。

単一の値(スカラー

単一の値として扱う。
where 列 = (副問い合わせ)

n行1列(ベクター)

複数の値として扱う。
where 列 any < (副問い合わせ)
where 列 all < (副問い合わせ)
where 列 in(副問い合わせ)

n行n列(マトリックス)

テーブルとして扱う。
select * from (副問い合わせ)
insert into (副問い合わせ) values ~
update (副問い合わせ) set ~
 
特殊な例
insert文の特殊構文。
INSERT INTO 家計簿集計テーブル(費目, 合計, 平均, 回数)
-----ここから先がVALUES以降の記述に相当する。------
SELECT
FROM 家計簿テーブル
SELECT 費目, SUM(出金額), AVG(出金額), 0
WHERE 出金額 > 0
GROUP BY 費目
----------------------------------------------
 

副問い合わせからNULLを除外する

SELECT * FROM 家計簿アーカイブ
WHERE 費目 IN (SELECT 費目 FROM 家計簿
WHERE 費目 IS NOT NULL)
 
SELECT * FROM 家計簿アーカイブ
WHERE 費目 IN (SELECT COALESCE(費目, 'ぬるぽ') FROM 家計簿) // NULLをぬるぽにする
 

テーブルの結合

いくつでもテーブル結合可能。
select 列
from tableA
join tabaleB
on 結合条件
join tableC
on 結合条件
join ~
 
SELECT 日付, 費目名
FROM 家計簿
JOIN 費目 -- 結合する他の表を指定
ON 家計簿.費目ID = 費目.ID -- 結合条件を指定
 

結合の処理イメージ

tableAの1行目に結合すべきtableBの行はどれかな?
というのを1行ずつ順番に処理するイメージ。
select *
from tableA //テーブルAに対して
join tableB //テーブルBを結合
on tableA.ID = tableB.ID //テーブルA.ID=テーブルB.IDになるように1行ずつ。
 

結合相手が複数の場合

行数が増える。
ID
名前
1
山田
2
佐藤
⇕結合
会員ID
ランク
1
ゴールド
2
シルバー
1
ブロンズ
上記2テーブルを結合
select ID, 名前, ランク
from tableA
join tableB
on tableA.ID = tableB.会員ID
山田さんが二人に増殖してしまう。
ID
名前
ランク
1
山田
ゴールド
1
山田
ブロンズ
2
佐藤
シルバー
 

結合相手の行がない場合

行数が減る。
ID
名前
1
山田
2
佐藤
⇕結合
会員ID
ランク
1
ゴールド
上記2テーブルを結合
select ID, 名前, ランク
from tableA
join tableB
on tableA.ID = tableB.会員ID
佐藤氏の消失。
ID
名前
ランク
1
山田
ゴールド
 

行数が減ると困る時は?

左部外部結合(left outer join)

左表の行数が減らない。
結合相手がない時はNULLが入る。
select 列
from 左テーブル
left outer join 右テーブル
on 結合条件
 
ID
名前
1
山田
2
佐藤
⇕左部外部結合
会員ID
ランク
1
ゴールド
佐藤氏無事。
ID
名前
ランク
1
山田
ゴールド
2
佐藤
NULL
 

右部外部結合(RIGHT OUTER JOIN)

右表の行数が減らない。

完全外部結合(FULL OUTER JOIN)

左右表の全行出力。

外部結合と内部結合の違い

結合すべき行が見つからない時に
外部結合は行が消滅しない、内部結合は行が消滅する。

複数条件で結合

select 列
from tableA
join tabaleB
on 結合条件 and 結合条件2

3つ以上のテーブル結合の処理順

select 列
from tableA
join tabaleB //まずAにBを結合
on 結合条件
join tableC //その後にCを結合
on 結合条件

副問い合わせテーブルと結合

n行m列の副問い合わせと結合できる。
slect *
form tableA
join (select * form tableB)
on A = B;
 

外部キーと主キー

基本的にはtableAの外部キーとtableBの主キーを指定して結合することが多い。
主キーは
  • 主キーはタプル(行)の一意識別能力を持つ(重複しない).
  • 主キーは空値(NULL)を含まない
外部キーとは
  • 外部キーの値は,参照先のリレーションの主キーの値から選ばれる.
  • 外部キーは空値(NULL)を含むことが許される.
 
外部キーと主キーの例↓
tableA
ID(主キー)
会員ID(外部キー)
名前
1
1
山田
2
2
佐藤
⇕結合(ON tableA.会員ID = tableB.会員ID)
tableB
会員ID(主キー)
ランク
1
ゴールド
2
シルバー
ID
名前
ランク
1
山田
ゴールド
2
佐藤
シルバー

トランザクション

トランザクションとは一塊の処理。
トランザクションは仮の書き換えで、コミットするまで確定しない。
 
もし停電してDBが止まっても、電源入れ直すとロールバック処理が走るんだって。すげー。
 

テーブルの作成(CREATE TABLE)

create table テーブル名 (列名, 列名の型名)
create table ABC (ID INTEGER, 日付 DATE)
 

テーブルの削除(DROP TABLE)

drop table テーブル名
 

テーブル定義の変更(ALTER TABLE)

列の追加

alter table テーブル名 add 列名 型 制約

列の削除

alter table テーブル名 drop 列名 型 制約
 

代表的な制約

NOT NULL

NULLは許されない!

UNIQUE

一意。
重複は許されない!

CHECK

ある列の値が妥当かをチェックする。
check(ID >= 0) // IDが0以上かをチェック

主キー(primary key)

  • 主キーの値を指定すれば、どの1行かを完全に特定できる。(重複不可)
  • NOT NULL。

外部キー(foreign key)

  • 外部キーの値は,参照先のリレーションの主キーの値から選ばれる.
  • 外部キーは空値(NULL)を含むことが許される.
書き方1
create table テーブル名(
列名 型 REFERENCES 参照先テーブル名(参照先列名))
書き方2
create table テーブル名(
foreign key (参照元列名) references 参照先テーブル名(参照先列名)
 

権限の付与・はく奪(GRANT/REVOKE)

grant 権限名 to ユーザー名// 権限の付与
reboke 権限名 from ユーザー名 //権限のはく奪
 

データベースの知識を深めよう

インデックス(CREATE INDEX)

インデックスとはDBの索引情報。 インデックスをつけると検索が高速になる。  
 
create index インデックス名 ON テーブル名(列名)
drop index インデックス名
drop index インデックス名 on テーブル名 (mysqlの場合)
 

インデックスのデメリット

インデックス作成のため、ディスク容量を消費する。
データ変更するときにインデックスも同時に書き換える必要が出る。
そのためINSERT・UPDATE・DELETEの処理が増える。  
 

ビュー

SQL分を短縮するのが目的。
何度も呼び出すテーブルをビューとして登録する。  
create view ビュー名 as select文
drop view ビュー名
 

採番

追加する行に独自の番号を振る。

AUTO_INCREMENT

いつも使ってるやつ。
1から順に自動連番。

SEQUENCE

シーケンスではデフォルト値や、1回の採番で増やす値、最大値などのオプションが使用可能。
create sequence シーケンス名;
drop sequence シーケンス名;
 

バックアップ

ACID特性

原子性:処理が中断しても中途半端な状態にならない。
一貫性:データの内容が矛盾しない。
分離性:複数の処理をどう実行しても副作用がない。
永続性:記録した情報は消滅せず保持され続ける。  
 

2つのファイルをバックアップ

データベースの内容そのもの:処理が重い。低頻度。
ログファイルの内容:処理軽い。高頻度。 DBのログファイルには実行した全てのSQL文が載っている。  
 

ロールフォワード

ログファイルを使って、障害発生の直前までデータ更新を進めること。
更新をキャンセルするロールバックの逆。  
 

DB設計

DB設計の流れ

概念設計

管理すべき情報がどのようなものかを整理。
RDBを意識せずに洗い出し。
情報同士の関連も整理。

論理設計

概念設計で明らかになった各情報について、RDBを使う前提で構造を整理し具体化。
どんなテーブルでどんな列を作るかまでを明らかにする。
ER図を作る。
型や成約などはまだ。

物理設計

特定のDBMS製品を使う前提で具体化する。
すべての列について型、インデックス、制約、デフォルト値など全ての要素を確定させる。
どんなSQL文を書くかまで落とし込む。
正規化もここでやる。
 

正規化

正規化の手順

非正規形→第1正規形→第2→第3

非正規形から第1正規形

・第1正規形の達成条件
テーブルのすべての行のすべての列に1つずつ値が入っている。
よって、繰り返しの列やセルの結合が現れてはならない。
 
下記の社員テーブルを第1正規形にしよう。
 
社員テーブル
部署番号
部署名
社員番号
社員名
役職コード
役職名
年齢
D1
開発1部
107
L
主任
31
121
R
一般
22
122
浅香あゆみ
R
一般
24
D2
開発2部
107
L
主任
31
112
C
副主任
29
 
1,繰り返し列を切り出す(行結合してない列のこと)
社員テーブルから繰り返し列を切り出し、社員番号テーブルを作る。
 
社員番号テーブル
社員番号
社員名
役職コード
役職名
年齢
107
L
主任
31
121
R
一般
22
122
浅香あゆみ
R
一般
24
107
L
主任
31
112
C
副主任
29
 
2,切り出し列の先から仮の主キーを選ぶ
社員番号列を主キーとする。
 
社員番号テーブル
社員番号
社員名
役職コード
役職名
年齢
107
L
主任
31
121
R
一般
22
122
浅香あゆみ
R
一般
24
107
L
主任
31
112
C
副主任
29
 
3,切り出し元の主キーをコピーし、切り出し先の複合主キーとする。
社員テーブルの部署番号をもってくる。
部署番号と社員番号の複合主キーとなる。
 
社員番号テーブル
社員番号
部署番号
社員名
役職コード
役職名
年齢
107
D1
L
主任
31
121
D1
R
一般
22
122
D1
浅香あゆみ
R
一般
24
107
D2
L
主任
31
112
D2
C
副主任
29
 
部署テーブル
社員テーブルから切り残された部分。
部署番号
部署名
D1
開発1部
D2
開発2部
これが非正規系から第1正規形への変形。
 
 

第1から第2正規形

・第2正規形の達成条件
複合主キーを保つテーブルの場合、非主キー列は複合主キーの全体に関数従属する。
よって、複合主キーの一部の列に対してのみ関数従属する列が含まれてはならない。
 

関数従属性

ある列Aの値が決まれば、自ずと列Bの値も決まるという関係。
このとき列Bは列Aに関数従属しているという。
 
例:金額が複合主キー(入出金ID+費目ID)に関数従属。
入出金ID+費目IDが確定すると金額が確定する。
入出金ID
費目ID
費目名
金額
41001
H01
住居費
65000
41001
H07
手数料
525
 

部分関数従属

穢らわしい関数従属のことw
複合主キーの一部の列にしか関数従属しないこと。
 
例:費目名が費目IDだけに関数従属。
費目IDだけが決まれば費目名が確定する。
入出金ID
費目ID
費目名
金額
41001
H01
住居費
65000
41001
H17
手数料
525
 
社員番号テーブルを第2正規形に変形しよう。
 
社員番号テーブル
社員番号
部署番号
社員名
役職コード
役職名
年齢
107
D1
L
主任
31
121
D1
R
一般
22
122
D1
浅香あゆみ
R
一般
24
107
D2
L
主任
31
112
D2
C
副主任
29
 
1,部分関数従属している列を切り出す。
 
社員テーブル
社員名
役職コード
役職名
年齢
L
主任
31
R
一般
22
浅香あゆみ
R
一般
24
L
主任
31
C
副主任
29
 
2,部分関数従属先の列をコピーし、主キーとする。
 
社員テーブル
社員番号
社員名
役職コード
役職名
年齢
107
L
主任
31
121
R
一般
22
122
浅香あゆみ
R
一般
24
107
L
主任
31
112
C
副主任
29
 
社員番号テーブル(切り残された部分)
社員番号
部署番号
107
D1
121
D1
122
D1
107
D2
112
D2
 
部署テーブル(ここはそのまま)
部署番号
部署名
D1
開発1部
D2
開発2部
これで第2正規形になった。
 

第2から第3正規形へ

第3正規形の達成条件
テーブルの非キー列は、主キーに直接関数従属すべきである。
よって、主キーに関数従属する列にさらに関数従属する列は存在してはならない。
 

推移関数従属

穢らわしい関数従属2w
主キーに対する間接的な関数従属。
 
例:きれいな関数従属
利用者IDが主キー入出金IDに関数従属。
入出金IDが決まれば利用者IDが決まる。
入出金ID
費目ID
利用者ID
利用者名
41001
2021/4/16
1
41001
2021/4/10
2
橘工事
 
例:推移関数従属
利用者名が利用者IDに関数従属。
そして利用者IDは入出金IDに関数従属。
つまり利用者名が入出金IDに間接的な関数従属。
入出金ID
費目ID
利用者ID
利用者名
41001
2021/4/16
1
41001
2021/4/10
2
橘工事
 
1,間接的に主キーに関数従属する列を切り出す。
社員テーブルから役職名列を切り出す。
 
役職テーブル
役職名
主任
一般
一般
主任
副主任
 
2,直接関数従属先だった列をコピーする。
 
役職テーブル
役職コード
役職名
L
主任
R
一般
R
一般
L
主任
C
副主任
 
社員テーブル
社員番号
社員名
役職コード(FK)
年齢
107
L
31
121
R
22
122
浅香あゆみ
R
24
107
L
31
112
C
29
 
部署テーブル
部署番号
部署名
D1
開発1部
D2
開発2部
 
部員テーブル
部署番号(FK)
社員番号(FK)
D1
107
D1
121
D1
122
D2
107
D2
112
 

最終的なER図

 

 

AWSメモ

 

料金アラート

無料枠があるからといって安心してはいけない。
枠内のはずなのになんか課金された。
 
・アラート設定方法
AWSマネジメントコンソール右上のアカウント名→
→マイ請求ダッシュボード
→Budgetsで予算を作成しよう。
予算超えたらメール来る。

 

参考動画

とにかくAWS公式動画が素晴らしいのでそれを見よう。
AWS公式の動画リンクは貼るとまずいのでEvernoteに貼った。
上から順にみると良い↓
 
AWS初心者向け】AWS学習方法まとめ【15時間で達成できる】
 
AWSハンズオンはじめの一歩:AWSアカウントの作り方&IAM基本のキ
 
AWS初心者向け Webinar 料金編 
 
AWSご利用開始時に押さえておきたい10のこと
 
AWS設計のベストプラクティスで最低限知っておきたい10のこと(上級者向け)
 
スケーラブルウェブサイト構築編(ハンズオン)
 

用語

  • SLA service lebe agreement サービス品質に関する取り決めのこと。提供社と受取社で決める。
  • SLA99.9%とは SLAを満たす状態=稼働状態 稼働状態を99.9%維持できますよということ。
  •  telnet コンピュータの遠隔操作
  •  SSH telnetの強化版。通信の暗号化。
  •  SSHクライアント teratermとかのこと。
  •  VPN virtual private network。仮想専用線。以前は物理的な専用線を用意して2点間をつないでいた。これを仮想的にインターネット上に作る仕組みのこと。例えば自社と取引先の専用線など。
  • VPC  AWSの仮想ネットワークの事。EC2とかRDSの入れ物。
  • VPCからネット接続はinternet gateway 
  • EC2 サーバ
  • RDS RDBサーバ
  • サブネット IPアドレス
  • クライアントからVPCへの接続はVPNゲートウェイ 
  • NAT 外部からのネット接続不可にする。内部からのネット接続は可。グローバルIPとプライベートIPの変換。
  • インスタンス。仮想サーバの単位。
  • AMI。インスタンス起動に必要な情報の塊。
  • AMIの作成→登録をしたら それを利用して新しいインスタンスを利用できる。
  • EBS。仮想外付けHDD。EC2は停止するとデータ消えるのでバックアップに。
  • S3。ストレージ。EBSとどう違うの?simple strage service
  • EBS と S3 の違い  EBSはEC2インスタンスへ直接接続。高速。容量少ない。
  • S3ではEC2インスタンスにアタッチすることはできません。低速。容量制限なし。
  • IAM AWSのユーザアカウント。細かく権限管理できる。 
  • ELB。ロードバランサ。トラフィックの負荷を自動的に分散。EC2が1つなら基本はいらない。
  • Iaas infrastructure as a service サーバ、コンピュータ、ストレージをクラウドで提供。
  • Paas platform as a service ハードウェアとOSをクラウドで提供。 
  • SaaS software as a service 普通のウェブアプリのこと。 

情報学へのとびら

放送大学情報コースの科目、情報学のとびらで学んだことのまとめ。

基本情報試験の範囲と近い。

教科書がわかりやすくてよかった。

授業はこれから見る予定。

1、情報化する社会を生きる

本科目の目的
  1. 情報リテラシー・ICTリテラシーの知識の習得
  2. 情報学の包括的な理解
 

2、情報デジタル表現とマルチメディア

デジタル情報処理の流れ

物理量→符号化→数値(列)→計算→数値(列)復号→物理量
 
デジカメに当てはめるとこんな感じ?
写真撮る(物理量)→符号化→数値(列)としてデータ保存→撮った写真を見る→計算→復号→画像表示(物理量)
 

符号化とは

符号化は情報の一面のみに着目した抽象化が行われる。
たとえば、文字は固有の番号(文字コード)に置き換えられる。
現実には文字情報には大きさや色、書体なども含まれているが、符号化ではこれらの情報は省かれる。
 
・標本化
電気信号を一定の時間間隔(周期)で計測すること。
計測の瞬間以外の情報はすべて捨てている。
例:音声の標本化
1秒間で100回音圧を計測。
 
標本化した値を一定の精度に丸めること。
例:標本化した値が36.944とする。
有効桁数3桁なら、四捨五入して36.9とする。
 

アナログ情報は劣化しやすい

例:写真の複製
撮った写真を現像して、またその写真を撮って現像を繰り返すと劣化していく
 

デジタル情報は劣化しにくい

誤り検出符号や誤り訂正符号でデータの誤りを防ぐ

誤り検出符号

誤りを検出する。
検出したらデータの再送依頼をして正確な情報を得る。
 
一定のビット数毎に1の数が奇数か偶数になるようにもう1ビットを加える方式。
例:1の数を偶数に
101100→1011001 1を加えて1の数を偶数にする。
110110→1101100 0を加えるので1の数は偶数のまま。
 
問題点:2つのビットが同時に誤っていた場合に誤りを検出できない。
例:110011→000011 どっちも1が偶数。
 

誤り訂正符号

検出するのではなく、訂正する。
例:元のビットを3つ連結する→1ビットごとに多数決で値を確定する。
1011→1011 1011 1011→1011で確定 全部正解
1011→0011 1011 1011→1011で確定 1桁目は0が1票 1が2票なので多数決で1になる
 
問題点:符号が3倍の長さになるので効率悪い。
たまたま同じ桁が誤っていたら訂正できない。
 

疑問:アナログとデジタルの境界とは?

例:音声のデジタル化の場合。
音をマイクで拾い、マイクの振動版を震わせ、その振動が電気信号に変換されて出力される。
その結果、音の波形と電気信号の波形が相似形になる。
ここまではアナログらしい。
電気信号に変換=デジタルだと思ってたけどそうじゃないみたい。
さらに標本化をするとデジタルになるようだ。
標本化によって捨てられる情報がある。
情報を削ぎ落すのがデジタル化?
アナログ:連続的
デジタル:離散的
離散的とは連続的ではないさま。数学で、値や数量がとびとびになっているさま。
 

3、コンピュータの構成要素とその機能

PCの構成要素

主記憶装置(メモリ)
中央演算装置(CPU)
入出力制御装置:周辺機器とのデータのやり取りの仲介
画像処理装置(GPU
その他の処理装置:音声処理装置やLANなど
バス:上記の装置間のデータのやり取りを行う通信経路
周辺機器:キーボード・マウスとか
チップセット:周辺素子をまとめたもの?
マザーボード:CPU・メモリ等の各装置を装着する基盤
I/O:CPUと周辺機器を接続し、データを入出力する。キーボード、マウス、HDD、ネットワーク、スピーカーなどとの接続。

コンピュータにおける計算の原理

否定(NOT)、論理積(AND)、論理和(OR)をいい感じに組み合わせると四則演算ができるらしいぞ。

2の補数

2進数で負の値を表現するためのもの。
10進数は数字の先頭に「-」を付けることでマイナスを管理(表して)いますが、2進数先頭1ビットが「1」の場合にマイナスであることを表します↓
2進数(4ビット)表現
2の補数
普通の2進数
0000
0
0
0001
1
1
0010
2
2
0011
3
3
0100
4
4
0101
5
5
0110
6
6
0111
7
7
↓ここから先が重要
先頭ビットが1のものは負とする↓
ここからも1ずつ増えていく↓
1000
-8
8
1001
-7
9
1010
-6
10
1011
-5
11
1100
-4
12
1101
-3
13
1110
-2
14
1111
-1
15
2の補数は2進数の符号を逆転する場合に使用する計算方法です。
・2の補数の出し方:ビットを反転して1を足す。
 10進数のー12=1100→0011+0001→0100
・2の補数と2進数の計算
例:4+(-2)
 0100 + 1110 =1 0010
 →溢れた1は取り除くと0010
 →答えは0010=2
・原理
 2の補数と元の2進数を足すと必ず0になる。
 N(元の2進数) + N2(2の補数)=0
 なので「N2=-N」ということになる。
 
 例:3
 0011+1101=1 0000 = 0
 こんな感じで必ず桁あふれで0になる。 
 

4、インターネットの歴史と仕組み

回線接続からパケット交換へ

昔の電話は2地点を電線で繋いで、アナログで音声を送っていた。
全ての家庭を直接電線で接続するのは不可能なので、電話局に交換盤を置いた。
交換盤を手動で繋ぎ変えて電話を繋いでいたらしい。
おもしろー。
 
交換盤にも限界があったので、1つの回線で異なる相手と通信できる方法が必要になった。
それがパケット通信方式。
送りたいデータを細かく分割し、データ自体に宛先情報を持たせた。
この1つの細かいデータをパケットという。
 

インターネットのパケット配送方式

パケットが持つ宛先とはIPアドレスのこと。
パケットがルータに送られるとバケツリレー方式で宛先に届く。

ルータの働き

パケットがルータに届く
→宛先が自分のネットワーク内ならそこに届ける
→他のネットワークなら経路表を元に隣接ルータに投げる
→経路表にもなかったらデフォルトゲートウェイに投げる

経路表(ルーティングテーブル)とは

IPアドレスの対照表とデフォルトゲートウェイが記入されたもの。
経路表は常に更新されていて、通信障害があっても迂回路を選択できる。
具体的には、
  1. 代表ルータに向けて各ルータが接続状態などの情報を送る。
  2. 代表ルータがその情報を元にネットワーク全体の地図を作り、各ルータに送る。
これを常にやっているらしい。すごすぎない?

ルータのさらに先は?

ルータ→中小プロバイダ→上位プロバイダ→インターネットエクスチェンジ(高速通信施設)
→再び上位プロバイダ→海底ケーブル!→海外へ
 

DNS(Domain Name System)による名前解決

DNSとはインターネットの住所録。
IPアドレスは数字の羅列でわかりづらいから、URLに変換する。
DNSドメインの階層構造に基づいて、1つのDNSサーバが1つの階層を受け持つ。
例えばwww.ouj.ac.jpなら下記の通り。
www.ouj.ac.jpへの問い合わせはキャッシュサーバ→ルートサーバ→jpサーバ→acサーバ→oujサーバと辿っていく。
 

インターネットの応用

さまざまなプロトコル

OSI参照モデル

番号が若いほど下位層。物理が最下位。アプリが最上位。
  1. 物理層:電圧や電波の周波数など物理的なプロトコル
  2. データリンク層:同一ネットワーク内で接続された通信機器とのデータ通信に関わるプロトコル
  3. ネットワーク層:ネットワークをまたがったデータ通信に関わるプロトコル。IPはココ。
  4. トランスポート層:データの信頼背の確保に関わるプロトコルTCPはココ。
  5. セッション層:通信相手との論理的な通信路の確立に関わるプロトコル
  6. プレゼンテーション層:データの表現形式の変換に関わるプロトコル。テキストや画像等の変換・逆変換。
  7. アプリケーション層:メールやうぇぶなどの特定の高度なデータ通信サービスに係るプロトコル。HTTP/SMTP/POP/IMAPはココ。
このような階層化を行い、上層及び下層とのデータ受け渡し方法を厳密化しておくことで、他の層に影響を与えずにプロトコル交換が可能になっている。
 

データのカプセル化

下位層→上位層
各層では、上位層より受け取ったデータに何も手を加えず、ヘッダと呼ばれるデータを付加し、それを下位層にわたす。
ヘッダにはその層で必要となる情報が入っている。
上位層から来た荷物を開けずに、その上からその層独自の梱包をかぶせて下位層に送るイメージ。
 
上位層→下位層
各層が下位層から受け取ったデータのヘッダ部を解析してからヘッダ部を除去して、適切な上位層のプロトコルに渡す。
これは下位層から来た荷物を開梱して中身だけを上位層に送るイメージ。
ある階層のプロトコルにとってみれば、それより下位層のプロトコルに関する情報は除去されているので、下位層のことを気にしなくてよい。
そのため各階層のプロトコルが交換可能になっている。
 
TCP: transmission control protocol。パケットの順番をそろえ、必要に応じて再送要求を行って完全なデータを復元する。
誤り検出や誤り訂正を行っているのかな?
 
UDP: user datagram protocol。パケットの誤り検出はするが訂正せずに破棄する。パケットの順番も気にしない。
データの正確性は低いが高速通信が可能。
 
ポート番号:パケットにポート番号という16ビットの数値を付けて、どのプログラムによって送受信されたか識別する。
例えば、IPアドレスだとPCまでは届く。
しかし、どのプログラムに届ければいいかわからないのでポート番号を使う。
 

情報セキュリティ技術

情報セキュリティ

機密性:許可されたものだけが情報にアクセスできること。
完全性:情報が正確で完全である事。
可用性:必要な時に情報にアクセスできること。
 

脆弱性

バッファオーバーフロー:プログラムが想定して否大きなデータが入力された時、データ用に確保していたメモリ領域を超えてデータが格納され、プログラムに書きかえが生じる恐れがある。
インジェクション:XSSSQLインジェクション。タグやSQL文の埋め込み。
DNSキャッシュポイズニング:DNSIPアドレスDNSキャッシュサーバに一時記憶する。キャッシしてあるホスト名とIPアドレスの対応情報を書きかえる。
マルウェア:コンピュータウイルス、ワーム、スパイウェア等の不正な行為を行うソフトウェアの総称。
  • ウイルスはプログラムやファイルに寄生して不正行為を行う。自己伝染・潜伏・発病機能の内1つ以上を持つもの。
  • ワームは寄生せずに単独実行可能なプログラム。
  • ボットは本来検索エンジンの情報収集を行うソフトウェア。DDoS攻撃を行うこともある。
  • トロイの木馬:正常な機能を持ったソフトウェアを装い、その裏で不正を働く。
  • スニファ:ネットワーク上のパケットをモニタする機器あるいはソフトウェアで、本来はネットワークの管理や研究開発用。盗聴に使用されることがある。
 

暗号

共通鍵暗号方式

暗号化のためのカギと復号化のためのカギが同一の暗号方式のこと。
例:アルファベットの暗号化
アルファベットを1文字ずらして暗号化する。
復号化するときも同じ。
japan→kbqbm
kbqbm→japan
 

公開鍵暗号方式

暗号化用と復号化用のペアになる鍵が生成される。
一方のカギで暗号化した暗号文はもう一方のカギでしか復号化できない。
暗号化した鍵では復号化できない。
また、一方のカギからもう一方のカギを生成、推測もできない。
つまり秘密鍵は復号化のみ。公開鍵は暗号化のみ。
例:Aさんが鍵のペアを生成。
→一方は秘密鍵として自分で保管
→一方は公開鍵としてBさんに渡す
→Bさんは公開鍵で文書を暗号化
→Aさんは秘密鍵で文書を復号化
→公開鍵が盗まれても、復号化できないから問題なし。
秘密鍵だけが盗まれなければ良い。
 

電子署名

公開鍵暗号方式電子署名にも利用される。
電子署名は、署名が本人のもので、メッセージに改ざんがないことを証明する。
電子署名はあくまでも本人確認が目的で、盗聴防止などはできないっぽい。(平文を送信するから)
例:Aさんの電子署名
Aさんはメッセージをハッシュ化する
→ハッシュ化されたメッセージ(メッセージダイジェスト)を秘密鍵で暗号化する
→この暗号化されたメッセージダイジェストが電子署名になる
秘密鍵で暗号化されているから、これを作成できるのはAさんのみという証明になる
→Bさんに電子署名とハッシュ化前の平文を渡す
→Bさんは平文をハッシュ化しメッセージダイジェスト生成
→さらにAさんの電子署名を復号化しメッセージダイジェストを得る
→2つのメッセージダイジェストが一致すれば改ざんがないことを確認できる
 

公開鍵基盤

公開鍵のなりすましを防ぐ仕組み。
Aさんから受け取った公開鍵が本当にAさんの物かを証明するもの。
認証局が本物であるという証明書を発行する。
HTTPSで使われている。
例:認証局がAの公開鍵を証明する
→BさんからAさんにデータを送りたい
→Aさんは認証局から証明書を受け取りBさんに送る
→Bさんは認証局の公開鍵で証明書の電子署名を検証
→その後にBさんはAさんの公開鍵でデータを暗号化しAさんに送信
 

プログラミング

プログラミング言語の変換方式

コンパイラ方式:プログラムを実行する前にソースコード全体を一度に機械語に変換する。
インタプリタ方式:ソースコードを逐次解釈し実行する。
中間言語方式:実行前にソースコードをCPUに依存しない中間言語コンパイルする。
実行時には仮想機械により解釈、実行される。
 
参考:5分で分かる教養としての低レイヤ -どうしてプログラムは動くのか(アセンブリ言語インタプリタJITコンパイラ)
 

OSによるハードウェアの抽象化

OS様々なハードウェアを抽象化している。
ユーザーにGUI操作を提供しているだけやないんやで。

CPUの抽象化

OSは短い間隔で実行するプログラムを切替えて、同時実行しているように見せている。
 

メモリの抽象化

物理的なメモリが細切れになっていると都合が悪い。
そこで仮想的なメモリアドレスを作り、細切れのメモリを繋ぎ合わせて仮想メモリとする。
 

補助記憶装置(HDD/SSD/DVD等)の抽象化

ファイル・ディレクトリ。
データをファイルとして統一的に扱えるように抽象化する。
ディレクトリ・フォルダによる階層化も抽象化である。
 

周辺機器の抽象化

周辺機器との接続はI/Oを通じて行われる。
例えば、プリンタなどは多くの製品があるが、プリンタなら製品に関わらずプリンタとして扱えるようにする。
 

APIとライブラリ

ハードウェアや他プログラムの隠ぺい。
プログラミングに置いてOSの機能を利用するにはOSが提供するアプリケーションプログラミングインタフェースAPI)を利用する。
APIを利用することによりハードウェアの詳細や同時に実行するほかのプログラムを意識せずプログラミンすることができる。
 

BIOS

ハードウェアの操作。
Basic Input /Output System
周辺機器の操作、I/Oの操作はOSではなくBIOS
BIOSはOSを含めた他のプログラムにI/Oを介したハードウェアの基本操作機能を提供している。
BIOSの機能はUFEIに移行してきている。
 

抽象化まとめ

プログラム
ライブラリ:OSによるAPIの差異を隠蔽
API:OSの機能を提供
OS:ハードウェアを抽象化
BIOS:直接I/Oを操作
 

ユーザインタフェース

インタフェースとは

interfaceとはもともと界面という意味を持つ。
界面とは液体と気体、液体と固体と言った質の異なるものの境界面の事。

ハードウェアインタフェース

ハード⇔ハード
複数のハードウェアのあいだでデータを転送するときに互いをつなげるケーブルのコネクタ形状、データのフォーマット、送受信の約束事(プロトコル)といったもののことです。
USB・HDMIwi-fiなど。
例:入出力制御装置I/OはCPUと周辺機器をつなぐ。

ソフトウェアインタフェース

ソフト⇔ソフト
プログラム間のデータやり取りの手順や方式を決めたもの。
OSが提供するAPIはソフトウェアがOSの機能を利用するインタフェース。

ユーザインタフェース

ユーザ⇔機械
ユーザと機械の間で情報をやり取りする仕組み。
入力インタフェース:キーボード、マウス、タッチパッドなど。
出力インタフェース:ディスプレイ、プリンタなど。
 

データベース

リレーショナルモデル

リレーショナルモデルでは、データをいくつかのデータ項目の組み合わせで表現する。

リレーションスキーマ

リレーションの構造を規定している情報。

リレーション

表のこと?

タプル

行のこと?

属性

列のこと?

リレーションの演算

射影

特定の列のみを抜きだす。
値が重複する行は除かれる。
※普通のRDBでは重複も表示される。

選択

特定の行のみを抜きだす。

結合

テーブル同士の結合。

直積(CROSS JOIN)

何の条件も付けずに2つのテーブルを結合すること。
対象となる2つのテーブルから行を1つずつ取り出し、合わせたものを新しい行とする演算。
新しいテーブルの行数=Aテーブルの行数×Bテーブルの行数、となる。
 
参考:直積結合とは
 
例:2行と2行のテーブルで直積すると4行
山田
10歳
田中
15歳
⇕直積
東京都
神奈川
結果↓
山田
10歳
東京都
山田
10歳
神奈川
田中
15歳
東京都
田中
15歳
神奈川

正規化

情報の損失が怒らないようにデータの重複を排除する手法。
 

ソフトウェアの開発

開発手法

ウォーターフォールモデル

要求分析・定義
外部設計
内部設計
実装
テスト
 

要件定義

目的:お客さんの要望を聞き、どんな機能が必要かユーザーと合意すること。
ユーザ向けに説明するための物。
ユーザとの話し合いで必要機能を洗い出す。

外部設計(基本設計)

目的:ユーザ向けの仕様設計。
画面設計・操作方法・ハード/ネットワーク構成・DB設計・セキュリティ。
開発するソフトと外部とのインタフェースの設計。
外部とはソフトの利用者や他のソフトなどのこと。
ユーザの目に触れる部分・ハード/ネットワーク構成・DB・既存ソフトの選定。
  • ソフトウェアの実現方法:ハードウェアやネットワークの構成、使用する既存のソフトの選定。
  • ソフトウェアの構成・構造:サブシステムへの分割方法、サブシステムの機能。
  • ユーザインタフェース:利用者が使うための画面設計。
  • データベース:DB設計。ER図を用いることが多い。

内部設計(詳細設計)

目的:実装者向けの設計。
外部設計で定めた仕様の実装方法を設計する。
仕様をどうコードに落とし込むかってところ。
外部設計はプログラミングを意識しない、内部設計は意識する。

実装

実装するw

単体テスト

目的:各機能の不具合検出。
各機能を1個ずつテスト。
例:検索機能のテスト。

結合テスト

目的:システム全体での不具合の検出。
各機能を組み合わせてテスト。
ここまでは開発環境で行うテスト。
例:登録機能+検索機能のテスト。
アカウント登録して検索でちゃんと出るか等。

総合テスト

目的:開発環境では見つからない不具合の検出。
本番に近い環境で行うテスト。
負荷テストとか。

受入テスト

目的:ユーザによる本番環境での不具合検出。
使用感の確認も目的の1つ。
ユーザが行うテスト。

リリース

納品すること。
ソフトウェアを1つのパッケージにまとめる。
バージョン番号を記載する。

アジャイル開発

アジャイル開発は特定の開発モデルではなく、様々な開発手法の総称!
知らなかった。
 

アドホックネットワーク

サーバーやアクセスポイント利用しないネットワークを指す。
アドホックad hoc)はラテン語で「一時的な、その場限り」の意。
「自立分散型無線ネットワーク」とも呼ばれる。
パソコン、携帯電話、タブレットなど、無線でネその場その場で動的に形成されるネットワークの事。
例:P2P無線LAN子機同士の接続。
 

ER図(実態関連図)の見方