okinawa

IT勉強メモ

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

コードファーストだと主キー名が「Id」か「classNameId」しかつけられない。

Companyクラスなら「Id」か「CompanyId」だけ。  

参考

キー-EF Core | Microsoft Docs

https://cloud6.net/so/asp.net-core/2495859

コードファーストの手順

  ・モデルクラスで[Key]付けるだけ。

[Key]
public int hogehoge {get; set;}

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

主キー名を変える場合は一度DBごと消さないとダメっぽい。

手順は

上記の要領でモデルクラス変更→

drop-database→Add-Migration→Update-Database

DBファースト

・コンテキストクラスを変更する。

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

                // モデルクラスの主キー指定
                entity.HasKey(e => e.AccountId);

                // DBの主キー名はaccount_id
                entity.Property(e => e.AccountId).HasColumnName("account_id");
             }

【.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 普通のウェブアプリのこと。