MySQLに日本語でINSERTできない場合


1. テーブル単位でEncodingタイプ設定

CREATE TABLE INSURANCE_RECOMM_TB (
id VARCHAR(10) PRIMARY KEY,
age int(5) NOT NULL,
sex VARCHAR(5) NOT NULL,
marriage VARCHAR(5) NOT NULL,
job VARCHAR(10) NOT NULL,
child VARCHAR(5) NOT NULL,
d_insurance VARCHAR(500),
c_insurance VARCHAR(500),
insurance_reason VARCHAR(500),
url VARCHAR(500)
)
ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;



2.Mysql設定でEncodingタイプ設定

MySQLは幾度もインストールしているが、毎回文字コードの設定では悩まされる。忘れてしまっていることもあるが、本質的に理解できていないので、毎回文字化けなどを起こしてしまうのだ。昨日も作成したデータベース日本語をINSERTしようとすると以下のようなエラーが出た。対応のメモを残しておく。

    Incorrect string value: '\xE3\x81\x95\xE3\x81\x82...' 
    for column 'NAME' at row 1 at com.mysql.jdbc

単に以下のようなINSERT文をJavaからexecuteUpdate()で実行しただけだ。同じことをMySQLコンソールからやった場合にはうまくいった。

    $ mysql -uroot -p***
    > use msql
    > create database test;
    > flush privileges; 
    > use test
    > create table DUMMY (
        ID      varchar(10)     primary key,
        NAME    varchar(20)     not null
    );
    > insert into DUMMY (ID, NAME) values ('001', 'たこはち');

以下のように対処した。まず、MySQLコンソールからcharacter_setをチェックしてみた。

    $ mysql -uroot -p***
    > use mysql
    > show variables like 'char%';
    +--------------------------+--------+
    | character_set_client     | latin1 |
    | character_set_connection | latin1 |
    | character_set_database   | latin1 |
    | character_set_filesystem | binary |
    | character_set_results    | latin1 |
    | character_set_server     | latin1 |
    | character_set_system     | utf8   |
    +--------------------------+--------+

character_set_databaseなどがlatin1になっているのでこれをsjisにする必要がある。MySQLインストール時にデフォルトのままだとlatin1(もしくはutf8)になる。スタートメニュー経由などでMySQL Server Instance Configuration Wizardを起動して、default character setの設定画面まで進める。このWizardは、以前、「MySQL 5.1.37のインストールで失敗」でも書いたように、何度も実行したことのあるMySQLInstanceConfig.exeだ。そこでデフォルトでlatin1になっているのをsjisに変更する。

また、MySQLインストール先にあるmy.iniファイルを開いてみて、default-character-set=latin1(もしくはutf8)となっていたら、それもsjisに変更する。Wizardを実行するとmy.iniファイルが更新されるが、必ずしもdefault-character-setは自動変更されないようなので、手作業で修正しておく。

    [mysql]
    default-character-set=sjis

    [mysqld]
    default-character-set=sjis

MySQLサービスを再起動後に、再度、MySQLコンソールからcharacter_setをチェックしてみる。

    $ mysql -uroot -p***
    > use mysql
    > show variables like 'char%';
    +--------------------------+--------+
    | character_set_client     | sjis   |
    | character_set_connection | sjis   |
    | character_set_database   | sjis   |
    | character_set_filesystem | binary |
    | character_set_results    | sjis   |
    | character_set_server     | sjis   |
    | character_set_system     | utf8   |
    +--------------------------+--------+

しかし、既存の作成済みのデータベースのcharacter_set_databaseは変わらないことに注意する必要がある。これはデータベースをdropして再作成するか、setコマンドで変更してやる必要がある。alter database文で文字コードを指定して変更することも、勿論可能だ。

    > use test
    > show variables like 'char%';
    +--------------------------+--------+
    | character_set_client     | sjis   |
    | character_set_connection | sjis   |
    | character_set_database   | latin1 |
    | character_set_filesystem | binary |
    | character_set_results    | sjis   |
    | character_set_server     | sjis   |
    | character_set_system     | utf8   |
    +--------------------------+--------+
    > set character_set_database = sjis;
    > show variables like 'char%';
    +--------------------------+--------+
    | character_set_client     | sjis   |
    | character_set_connection | sjis   |
    | character_set_database   | sjis   |
    | character_set_filesystem | binary |
    | character_set_results    | sjis   |
    | character_set_server     | sjis   |
    | character_set_system     | utf8   |
    +--------------------------+--------+

setコマンドでの変更も一時的には有効だ。しかし恒久的なものではなく、MySQLサービスが再起動されると元に戻ってしまう。以前には、サービス起動の引数でcharacter_setを指定したこともあるが、今回はやめておく。一番いいのは、作成済みのデータベースを一旦drop databaseして新たにcreate databaseする方法だろう。まだ実データがない開発段階では、それが望ましい。新規に作成したデータベースのcharacter_set_databaseにはsjisが適用されるようになる。

    > use test
    > show variables like 'char%';
    +--------------------------+--------+
    | character_set_client     | sjis   |
    | character_set_connection | sjis   |
    | character_set_database   | latin1 |
    | character_set_filesystem | binary |
    | character_set_results    | sjis   |
    | character_set_server     | sjis   |
    | character_set_system     | utf8   |
    +--------------------------+--------+
    > drop database test;
    > create database test;
    > use test
    > show variables like 'char%';
    +--------------------------+--------+
    | character_set_client     | sjis   |
    | character_set_connection | sjis   |
    | character_set_database   | sjis   |
    | character_set_filesystem | binary |
    | character_set_results    | sjis   |
    | character_set_server     | sjis   |
    | character_set_system     | utf8   |
    +--------------------------+--------+

ちなみにJavaMySQLからデータベースに接続するときは、勿論、以下の感じでcharacterEncodingにSJISを指定しておくこと。

    try {
        DbUtils.loadDriver("com.mysql.jdbc.Driver");
    } catch (Exception ex) {
        ;
    }
//  String url = "jdbc:mysql://localhost/test?useUnicode=true&characterEncoding=SJIS";
    String url = "jdbc:mysql://localhost/" + "test"; // database名がtestの場合
    Properties props = new Properties();
    props.put("user",       "root");                 // 任意
    props.put("password",   "***");                  // 任意
    props.put("useUnicode", "true");                 // これが必要
    props.put("characterEncoding", "SJIS");          // これが必要
    try {
        this.conn = DriverManager.getConnection(url, props);
    } catch (SQLException ex){
        ;
    }

[2010/02/02追記]

文字コード関連の変数についての情報があったので追記しておく。文字コードはcreate database文やalter database文でが指定でき、databaseごとに使い分けが行える。character_set_database, character_set_client, character_set_connection, character_set_resultsは同じ文字コードに設定しておくことが無難そうだ。

変数内容
character_set_systemシステムがテーブル名やカラム名などの登録する際に使用する文字コード。utf8で固定されている。
character_set_servercharacter_set_databaseのデフォルト値となる文字コード
character_set_databasecreate database文で文字コードが指定されなかった場合、作成されたdatabaseの文字コードはこれになる。character_set_connectionのデフォルト値になる。
character_set_clientサーバクライアントから受け取るSQL文の文字コード
character_set_connectionクライアントから受け取ったSQL文をサーバが、この文字コードに変換して取り込む。通常は、character_set_client,character_set_connection,character_set_resultsは同じ文字コードにする。
character_set_resultsサーバクライアントに返す結果の文字コード。この変数をnullに設定すると、結果に対する文字コード変換は行われない。

データベース作成流れ

データベース作成(スキーマ作成)

→テーブル作成

→ユーザー作成

→権限付与

→Mysql稼働


データベース作成




データベースを作成するSQL文は以下の通りです。

mysql -u root -- rootでログイン

 CREATE DATABASE データベース名
 [CHARACTER SET = 文字コード名, COLLATION = COLLATION名];

 ※ []内は必須ではないオプションです

データベース作成時に利用できるオプションは文字コードCHARACTER SETおよび文字の照合順序COLLATION です。サーバ全体で文字コードを指定している場合には個別のデータベースで再度指定する必要は通常はありません。なんらかの理由で特定のデータベースの文字コードを変更したい場合のみに変更します。

文字の照合順序とは、例えばひらがなとカタカナ、または全角と半角のある文字、またはを別の文字を同一の文字と見なすかなどを挙動を設定します。どのような文字か同一と見なされるかは、MySQLユーザ会会長とみたまさひろさんのブログにまとめられていますので参照してください。


テーブル作成


データベースを作成するSQL文は以下の通りです。主なオプションのみ記載します。

CREATE TABLE テーブル名
  (列の定義) [テーブルオプション]

列の定義は、列の名称とデータ型、列のオプションの組み合わせになります。列のオプションでは、その列をインデックスに指定する場合は種類などが設定できます。他にも列ごとに文字コードを定義することや、初期値および制約の設定もオプションとして設定可能です。具体的な構文の例は後ほど改めて紹介します。

インデックスの種類
種類定義オプション名詳細
主キーPRIMARY 行を識別するための列。重複する値は格納できず、NULLも格納できない。
ユニークキーUNIQUE主キーに似て、重複する値は格納できないが、NULLは格納できる。
ノンユニークキーKEY重複する値は格納できる。
空間インデックスSPATIAL座標などの空間情報を格納するための特殊なインデックス ※MyISAMのみ
全文検索インデックスFULLTEXT全文検索のための特殊なインデックス ※日本語非対応



ユーザー作成

mysql -u root -- rootでログイン create user {user名}@localhost identified by {パスワード} -- ユーザー作成

作成したユーザーの確認

use mysql -- DB'mysql'に移動 select user,host from mysql.user -- ユーザーを確認

権限追加

構文

grant {権限内容} on {権限対象} to {ユーザー名}@{ホスト名} identified by {パスワード}
*権限対象はdatabase.tableで構成。test_db.*はtest_dbのあらゆるTableへの権限付与を意味


*Mysql버전 8부터 identified 이후가 없어짐

grant select on test_db.* to test@{権限付与対処のIPアドレス} identified by {パスワード};

->

grant select on test_db.* to test@{権限付与対処のIPアドレス}

-- test_dbのselect権限をtestユーザーに追加 grant select on test_db.* to test@{権限付与対処のIPアドレス} identified by {パスワード}; -- test_dbの全権限をtestユーザーに追加 grant all on test_db.* to test@{権限付与対処のIPアドレス} identified by {パスワード}; -- 全DBの全権限をtestユーザーに追加 grant all on *.* to test@{権限付与対処のIPアドレス} identified by {パスワード};


--権限確認

SHOW GRANTS for 'hoge'@'%';



追加した権限の確認

  • dbテーブル

host名、db名、user名、追加されている権限一覧を確認

    select user,host from mysql.user


    • 追加したdbへのアクセス
    -- 作成したユーザーでログイン
    mysql -u test -p
    
    -- db確認。 権限を追加したDBを確認できる。
    show databases
    


    • 外部から追加したdbへのアクセス
    • -- 作成したユーザーでログイン mysql -h [ターゲットのDBサーバー] -u test -p -- db確認。 権限を追加したDBを確認できる。 show databases


    権限削除

    構文

    revoke {権限内容} on {権限対象} to {ユーザー名}@{ホスト名} identified by {パスワード}

    -- testユーザーからfile権限を削除
    revoke file on *.* from test@localhost;





    Mysql稼働・停止


    制御スクリプトオプション

    オプション操作
    startmysqld デーモンを起動します。
    stopmysqld デーモンを停止します。
    restartmysqld デーモンを再起動します。
    statusmysqld デーモンの起動状況を確認します。
    condrestartmysqld デーモンが動作しているかを確認後、再起動します。(/var/lock/subsys/mysqld が存在するとき再起動します。)

    MySQL を起動するには、以下のコマンドを実行します。

    # /etc/init.d/mysqld start

    MySQL を停止するには、以下のコマンドを実行します。

    # /etc/init.d/mysqld stop

    Turbolinux 11 Server 起動時に MySQL を自動的に開始するには、以下のように chkconfig コマンドを実行しておきます。

    # chkconfig mysqld on









    함수적 종속성은 정규화를 이해하기 위해 필요한 개념입니다.



    1. 함수적 종속성


    함수적 종속성은 애트리뷰트들 사이의 관계에 대한 제약조건으로 애트리뷰트 A가 B의 결정자이면, 다음의 조건을 따라야 합니다.


    A이면 B이고 동시에 A이면 C일 수 없지만, B이면 반드시 A인 것은 아니다.


    재미있는 말로하자면, A는 B라는 한명의 파트너만 만나야하지만 정작 A의 파트너인 B는 A이외의 파트너도 만날 수 있는 난봉꾼입니다. 때문에 A는 B에 종속적이라고 표현합니다.


    예를들어 아래의 테이블에서 


    사원번호와 이름이 각각 123456, 이진욱

    사원번호와 이름이 각각 567890, 이진욱


    인 동명이인의 사원이 존재한다고 합시다. 이때, 사원번호를 A속성, 이름을 B속성이라고 한다면, A이면 반드시 B이지만, B이면 반드시 A라고 할 수 없습니다. 따라서, B는 A를 종속하고 있습니다.


     


    2. 결정자(determinant)


    결정자는 주어진 릴레이션에서 다른 애트리뷰트를 고유하게 결정하는 하나 이상의 애트리뷰트입니다.


    아래그림에서 사원릴레이션에 사원번호와 부서번호 2개가 결정자로 사원번호는 사원이름, 주소, 전화번호를 고유하게 결정하고 부서번호는 부서이름을 고유하게 결정합니다.


     


     

     


    3. 완전함수적 종속성(FFD: Full Functional Dependency)


    사원 릴레이션에 있는 2개의 결정자를 모두 종속하는 경우(직책)가 완전함수적 종속성이고 둘 중 하나의 결정자에만 종속되는 경우(사원이름, 주소, 전화번호는 사원번호에 부서이름은 부서번호)는 부분 함수적 종속성입니다. 



    [완전함수적 종속성과 부분함수적 종속성 구분]

     

     


    4. 이행적 함수적 종속성(transitive FD)


    (1) fd1 : 학과이름과 학과전화번호는 학번에 부분적함수적 종속성


    (2) fd3 : 학점은 학번과 과목번호에 완전함수적 종속성


    (3) fd2 : 학과전화번호는 학번(결정자)에 의해 부분적 종속성을 가지면서 학번의 또다른 부분함수적 종속성인 학과이름에 함수적종속을 가지는데 이럴경우를 학과전화번호는 이행적 함수적 종속성을 가집니다. 


     


    1. 식별자 정의

    식별자란 하나의 엔티티(테이블) 내에서 각각의 인스턴스(로우)를 유일(Unique)하게 구분해 낼 수 있는 속성(컬럼) 또는 속성 그룹을 말하며, 하나의 엔티티는 하나 이상의 식별자를 반드시 보유하고 있어야만 한다. 즉, 쉽게 정리하면 중복 데이터가 없는 속성(컬럼)을 의미한다.



    2. 식별자의 유형

    1) 주식별자 / 보조식별자 : 대표성 여부


    하나의 엔티티 내에서 식별자로 사용할 수 있는 하나 이상의 키들을 후보식별자라 하고, 그 중 엔티티의 대표성을 나타내는 유일한 식별자를 주식별자, 나머지를 보조식별자로 활용한다.


    물리모델에서 주식별자는 PK 역할, 보조식별자는 유니크 인덱스로 지정


        예 )  사원 : 후보식별자 - 사번, 주민번호


                         주식별자 - 사번


                         보조식별자 - 주민번호 



    2) 내부식별자 / 외부식별자 : 스스로 생성 여부


    자신의 엔티티 내에서 스스로 생성되어 존재하는 식별자를 내부식별자, 다른 엔티티로부터 관계에 의해 주식별자 속성을 상속받아 자신의 속성에 포함되는 식별자를 외부식별자라한다.


    외부식별자는 FK를 의미한다. 



    3) 단일식별자 / 복합식별자 : 단일 속성 여부


    주식별자의 구성이 한 가지 속성으로 이루어진 경우를 단일식별자, 두 개 이상의 속성으로 구성된 경우를 복합식별자라 한다.


    복합실별자의 경우는 우선순위가 매우 중요하다. 





    위의 테이블에서 주문번호와 상품코드를 복합시켜야만, 식별자로써의 기능을 하게 되는데 주문번호와 상품코드를 복합식별자라고 한다.



    ■ 자주 사용되는 속성은 우선순위가 높다. 


     db11.png

     

    대체적으로 자식 엔티티의 PK의 우선순위의 앞 순위에 부모로부터 상속받은 속성을 두는 것이 좋다. 부모로부터 상속받은 PK의 속성은 SQL의 조인에서 반드시 사용되어지고 WHERE 절에서 사용 가능성이 높다.

     

      

    ■ 분포도가 좋은 속성은 우선순위가 높다.

    분포도가 좋다는 의미는 사원번호, 주민번호와 같이 자료의 식별성이 뛰어난 속성으로 SQL 사용시 분포도가 좋은 속성으로 접근하면 그만큼 적은 범위의 자료에만 접근할 수 있다. 


    구분 표시와 같은 속성은 분포도가 매우 낮은 속성이므로 우선순위가 낮다. 


    PK가 사원구분 + 사원번호라면 조회 유형은 사원번호에 의한 경우, 사원번호 + 사원구분, 사원구분에 의한 경우인데, 사원번호에 의한 경우 인덱스를 사용할 수 없고,


    사원구분에 의한 경우도 분포도가 매우 낮은 속성이므로 풀 스캔하는 것이 빠르다. 



    ■ ' = ' 조회를 하는 속성은 우선순위가 높다.


    날짜와 같은 속성은 대부분이 기간을 조회하므로, 인덱스의 첫번째 속성이 LIKE 조회나 BETWEEN 조회를 하게 되어 인덱스를 사용하지 못하게 된다. 

     db12.png

    퍼온글입니다. 원글 출처 : http://3months.tistory.com/193







    데이터베이스 정규화 1NF, 2NF, 3NF, BCNF



    정규화를 이해하기 위해서는 아래의 키워드들을 이해하고 있어야 하며, 정규화에 대한 사전 작업으로 다음의 스텝을 따라야할 필요가 있습니다.


    1. 이해해야할 키워드

    식별자와 비식별자의 구분(http://valuefactory.tistory.com/221?category=768571)

    식별자그룹 : (복합식별자) 혹은 (주식별자+보조식별자)

    비식별자그룹(일반 속성) : 식별자 그룹을 제외한 그 외의 속성(컬럼)들

    종속관계(http://valuefactory.tistory.com/222?category=768571)



    2. 정규화전 따라야할 스텝

    a. 엔티티의 속성을 노트에 써봅니다.

    b. 각 속성을 식별자 그룹과 비식별자 그룹으로 나눈 후, 식별자 그룹에 네모 박스를 그려줍니다.

    c. 아래의 정규화과정에 따라, 정규화를 검증해봅니다.



    데이터베이스 정규화란 데이터베이스의 설계를 재구성하는 테크닉입니다. 정규화를 통해 불필요한 데이터(redundancy)를 없앨 수 있고, 삽입/갱신/삭제 시 발생할 수 있는 각종 이상현상(Anamolies)들을 방지할 수 있습니다. 


    데이터베이스 정규화의 목적은 주로 두 가지입니다.



    1. 불필요한 데이터(data redundancy)를 제거한다.


    2. 데이터 저장을 "논리적으로" 한다. 




    여기서 2번 데이터 저장을 논리적으로 한다는 것은 데이터 테이블의 구성이 논리적이고 직관적이어야한다는 것입니다. 



    우선 정규화를 안 했을 때의 문제점에 대해서 알아보겠습니다.




    위와 같이 정규화가 되지 않은 구조의 테이블(Adam이라는 학생이 두 번 들어가 있습니다.)의 경우, 데이터 핸들링시 다양한 이상현상이 발생하게 됩니다.



    1. Update : Adam의 Address가 변경되었을 때, 여러줄의 데이터를 갱신해야합니다. 이로인해 데이터의 불일치(inconsistency)가 발생할 수 있습니다.



    2. Insert : 만약 학생이 아무 과목도 수강하지 않는다고 하면, Subject_opted 컬럼에는 NULL이 들어갈 것입니다. 



    3. Deletion : 만약 Alex 학생이 과목 수강을 취소한다면 Alex의 레코드가 아예 테이블에서 지워져버립니다.



    위와 같이 정규화가 제대로 되지 않은 테이블의 경우 갱신/삽입/삭제 시 다양한 문제점이 발생할 수 있습니다. 이를 테이블의 구성을 논리적으로 변경하여 해결하고자 하는 것이 바로 정규화입니다.



    정규화의 법칙(Normalization Rule)은 1차정규화, 2차정규화, 3차정규화, BCNF, 4차정규화, 5차정규화로 나눌 수 있는데, 실무적으로 4차, 5차 정규화까지 하는 경우는 많지 않다고 합니다. 따라서 이 포스팅에서도 BCNF까지만 알아보겠습니다.




    1. 1차 정규화


    1차 정규형은 각 로우마다 컬럼의 값이 1개씩만 있어야 합니다. 이를 컬럼이 원자값(Atomic Value)를 갖는다고 합니다. 예를 들어, 아래와 같은 경우 Adam의 Subject가 Biology와 Maths 두 개 이기 때문에 1차 정규형을 만족하지 못합니다.




    위의 정보를 표현하고 싶은 경우 이렇게 한 개의 로우를 더 만들게 됩니다. 결과적으로 1차 정규화를 함으로써 데이터 redundancy는 더 증가하였습니다. 데이터의 논리적 구성을 위해 이 부분을 희생하는 것으로 볼 수 있습니다.





    2. 2차 정규화



    2차 정규화의 조건

    ・2차 정규형은 엔티티의 모든 속성이 후보 식별자 전체에 종속적이어야 합니다.

    ・만약, 일반 속성중에서 후보 식별자 전체에 종속적이지 않고 속성 일부에 종속적인 속성이 존재할 경우, 이를 분리해야합니다.

    ・즉, 모든 비식별자 속성은 후보 식별자 속성에 완전함수 종속이 되야하며, 부분함수종속이 될 경우 이를 분리해야합니다.

    ・2차 정규형은 복합 식별자를 구성하는 속성이 두개 이상인 경우에만 대상이되고, 단일 속성으로 주식별자가 구성될 경우 대상이 아닙니다.






    2차 정규화부터가 본격적인 정규화의 시작이라고 볼 수 있습니다. 2차 정규형은 테이블의 모든 컬럼이 완전 함수적 종속을 만족하는 것입니다. 이게 무슨 말이냐면 기본키중에 특정 컬럼에만 종속된 컬럼(부분적 종속)이 없어야 한다는 것입니다. 위 테이블의 경우 기본키는 (Student, Subject) 두 개로 볼 수 있습니다. 이 두 개가 합쳐져야 한 로우를 구분할 수가 있습니다. 근데 Age의 경우 이 기본키중에 Student에만 종속되어 있습니다. 즉, Student 컬럼의 값을 알면 Age의 값을 알 수 있습니다. 따라서 Age가 두 번 들어가는 것은 불필요한 것으로 볼 수 있습니다.




    Student Table




    Subject Table




    이를 해결하기 위한 방법은 위처럼 테이블을 쪼개는 것입니다. 그러면 두 테이블 모두 2차 정규형을 만족하게 됩니다. 위 테이블의 경우 삽입/갱신/삭제 이상을 겪지 않게됩니다. 하지만 조금 더 복잡한 테이블의 경우, 갱신 이상을 겪기도하는데 이를 해결하는 것이 바로 3차 정규화입니다.




    3. 3차 정규화



    3차 정규화의 조건

    ・일반 속성 간의 함수적 종속 관계를 분해






    이와 같은 데이터 구성을 생각해봅시다. Student_id가 기본키이고, 기본키가 하나이므로 2차 정규형은 만족하는 것으로 볼 수 있습니다. 하지만 이 데이터의 Zip컬럼을 알면 Street, City, State를 결정할 수 있습니다. 또한 여러명의 학생들이 같은 Zip코드를 갖는 경우에 Zip코드만 알면 Street, City, State가 결정되기 때문이 이 컬럼들에는 중복된 데이터가 생길 가능성이 있습니다. 정리하면 3차 정규형은 기본키를 제외한 속성들 간의 이행적 함수 종속이 없는 것 입니다. 풀어서 말하자면, 기본키 이외의 다른 컬럼이 그외 다른 컬럼을 결정할 수 없는 것입니다. 




    3차 정규화는 2차정규화와 마찬가지로 테이블을 분리함으로써 해결할 수 있는데, 이렇게 두 개의 테이블로 나눔으로써 3차 정규형을 만족할 수 있습니다. 이를 통해 데이터가 논리적인 단위(학생, 주소)로 분리될 수 있고, 데이터의 redundancy도 줄었음을 알 수 있습니다.




    4. BCNF


    BCNF는 (Boyce and Codd Normal Form) 3차 정규형을 조금 더 강화한 버전으로 볼 수 있습니다. 이는 3차 정규형으로 해결할 수 없는 이상현상을 해결할 수 있습니다. BCNF란 3차정규형을 만족하면서 모든 결정자가 후보키 집합에 속한 정규형입니다. 아래와 같은 경우를 생각해보면, 후보키는 수퍼키중에서 최소성을 만족하는 건데, 이 경우 (학생, 과목) 입니다. (학생, 과목)은 그 로우를 유일하게 구분할 수 있습니다. 근데 이 테이블의 경우 교수가 결정자 입니다.(교수가 한 과목만 강의할 수 있다고 가정) 즉, 교수가 정해지면 과목이 결정됩니다. 근데 교수는 후보키가 아닙니다. 따라서 이 경우에 BCNF를 만족하지 못한다고 합니다. 3차 정규형을 만족하면서 BCNF는 만족하지 않는 경우는 언제일까요? 바로 일반 컬럼이 후보키를 결정하는 경우입니다. 


    학생

    과목 

    교수 

    학점 

     1

    AB123

     김인영

     A

     2

     CS123

     Mr.Sim

     A

     3

     CS123

     Mr.Sim 

     A




     위와 같이 테이블이 구성된 경우에 데이터가 중복되고, 갱신 이상이 발생합니다. 예를 들어 Mr.Sim이 강의하는 과목명이 바뀌었다면 두 개의 로우를 갱신해야합니다. 이를 해결하기 위해서는 마찬가지로 테이블을 분리합니다.




    교수 테이블


    교수

    과목

     김인영

    AB123 

     Mr.Sim

    CS123 




    수강 테이블

    학생

    교수 

    학점 

     1

     김인영

     A

     2

     Mr.Sim

     A

     3

     Mr.Sim

     A



    참고


    http://www.studytonight.com/dbms/database-normalization.php


    http://pronician.tistory.com/922



    root사용자의 비번을 알 경우

    1
    2
    C:> mysql -u root -p //root로 로그인
    C:> password :
    cs





    모든 사용자 확인

    1
    SQL > SELECT Host, User FROM mysql.user;
    cs




    데이터베이스 사용자 계정으로 로그인


    1
    2
    3
    4
    5
    c:/ > sqlplus "/as sysdba"
     
    SQL > show user
     
    SQL > select * from all_users;
    cs





    mysql 인스톨 후 root사용자의 임시비밀번호 발급 및 비밀번호 변경

    sudo grep 'temporary password' /var/log/mysqld.log
    Copy

    The output should look something like this:

    2018-05-23T10:59:51.251159Z 5 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: q&0)V!?fjksL
    Copy

    Make note of the password, because the next command will ask you to enter the temporary root password.

    Run the mysql_secure_installation command to improve the security of our MySQL installation:

    sudo mysql_secure_installation
    Copy
    Securing the MySQL server deployment.
    
    Enter password for user root:
    Copy

    After entering the temporary password you will be asked to set a new password for user root. The password needs to be at least 8-characters long and to contain at least one uppercase letter, one lowercase letter, one number, and one special character.

    The existing password for the user account root has expired. Please set a new password.
    
    New password:
    
    Re-enter new password:
    Copy

    The script will also ask you to remove the anonymous user, restrict root user access to the local machine and remove the test database. You should answer “Y” (yes) to all questions.







    계정 분실 시 사용자 계정으로 로그인


    sqlplus "/as sysdba" 로 로그인 하는경우에는 system 계정 패스워드 파일을 사용하거나 OS 인증을 사용한다.


    OS 인증의 경우에는 윈도우에서 ORA_DBA 그룹, 유닉스에서 dba 그룹인 경우 오라클이 설치된 컴에 administrator로 접속한 다음



    1
    2
    3
    4
    5
    6
    7
    C:\>sqlplus /nolog
     
    SQL > conn /as sysdba  - sys 로 로그인 한 경우와 같기 때문에 System계정의 암호를 변경 할 수 있다.
     
    SQL > alter user system identified by NEW_PASSWORD; - system의 새로운 비번 설정
     
    SQL > alter user sys identified by NEW_PASSWORD; - sys의 새로운 비번 설정
    cs



    *sys와 system 관리자의 차이

    1. SYS

    DBMS의 데이터 딕셔너리 소유자, 오라클 데이터베이스 관리자(SUPER USER)

    디폴트 패스워드 : change_on_install(8i 이전버전)

    DB생성 가능


    2. SYSTEM

    SQL*FORMS등 툴을 위한 데이터딕셔너리 소유자

    디폴트 패스워드 : manager(8i 이전버전)

    권한은 SYS와 같으나 DB생성 권한은 없음


    3. scott

    샘플 사용자 계정

    디폴트 패스워드: tiger




    계정 생성(계정생성은 시스템관리자 로그인 후 가능하다)

    1
    SQL > CREATE USER valuefactory identified by 1234; -패스워드 변경도 가능
    cs


    http://valuefactory.tistory.com/287?category=777823에서 계정생성시 권한부여에 대한 자세한 내용참고




    권한부여

    1
    SQL>grant connect, resource to valuefactory;
    cs


    http://jihwan4862.tistory.com/78 에서 권한 부여에 대한 자세한 내용 참고



    계정 삭제


    1
    SQL > drop user valuefactory cascade;
    cs


    ・관계형 스키마 작성

    -정형화가 잘 되어 있어서 7가지의 단계를 따라가면 er다이아그램이 관계형스키마로 맵핑된다.




    ・1단계 : 엔티티 타입을 관계형 스키마로 맵핑

    -E1이라는 엔티티 타입이름이 테이블의 이름이 됨

    -키애트리뷰트는 밑줄!





    ・2단계 : 위크 엔티티타입을 관계형 스키마로 맵핑

    -참조하는 테이블의 기본키(PK)를 애트리뷰트로 가져와 fk를 준다.

    -약한 엔티티타입은 pk가 될 수 있는 애트리뷰트가 존재하지 않기때문에 약한 엔티티타입의 부분키(PK1)와 참조하는 테이블의 기본키(PK)를 복합키로 생성하여 약한 엔티티타입의 기본키를 만든다.





    ・3단계 : 1:1 관계 타입의 변환

    -1:1과 1:n 관계는 fk를 통해 서로 연결된다.

    -er에서 두줄을 가지고 있는 쪽(전체참여)에 fk를 준다.





    ・4단계 : 1:n 관계 타입의 변환

    -n쪽에다가 fk를 준다.





    ・5단계 : n:m 관계 타입의 변환

    -1:1관계와 1:n관계에서는 한쪽에 fk를 주지만, n:m관계에서는 새로운 릴레이션R을 생성해 그 릴레이션에 fk를 준다.

    -새로 생성된 릴레이션R은 양쪽의 엔티티타입에서 가져온 두개의 pk를 fk로 삼는다.(fk 2개)

    -fk가 되는 두개의 애트리뷰트가 합쳐진 복합키가 릴레이션R의 기본키가 된다.



    ・6단계 : 다치 에트리뷰트를 관계형 스키마로 맵핑

    -다치애트리뷰트를 제외한 애트리뷰트로 관계형 스키마를 생성한다.

    -다치애트리뷰트는 따로 빼내어, 다치애트리뷰트의 이름으로된 릴레이션을 새로 만든다

    -참조하는 테이블의 기본키를 새로운 릴레이션의 fk로 지정한다.

    -참조하는 테이블의 기본키와 다치애트리뷰트외 이름으로된 애트리뷰트를 생성하고, 두 애트리뷰트의 복합키를 pk로 사용한다.




    ・7단계 : 3차 관계타입을 관계형 스키마로 매핑

    -5단계와 동일







    실제 ER모델링을 관계형 스키마로 맵핑해보자!


    *관계형 스키마의 인풋이 되는 ER모델




















    *완성된 모습의 관계형 스키마






















    ・개념적인 설계에서 논리적인 설계로 나아가기

    -개념적인 설계에서 논리적인 설계로 맵핑을 해보자

    -개념적 설계의 산출물인 er다이어그램은 인간이 이해하기 쉬운 것

    -논리적 설계로 넘어가면서 점차 컴퓨터가 이해할 수 있는 모델들로 바꾸어야함

    -논리적 모델로써 relational model을 사용함

    -논리적 설계의 아웃풋은 relational schema

    -개념적 설계에서 논리적 설계로 맵핑하는 과정은, db 설계 전반중 가장 정형화되고 기계적으로 가능함

    -즉, 정해진 메뉴얼대로 하란대로만 하면됨. 이해하기 쉬움


    ・논리적 설계

    -정의 : 개념적 설계의 아웃풋인 er다이아그램을 데이터베이스 관리 시스템에 매빙하는 것

    -아웃풋은 relational schema





    ・용어설명을 통해 관계형 데이터베이스 알아보기


    -테이블 네임 = 릴레이션 네임(테이블을 릴레이션이라고 부름) = (개념적 설계에서)엔티티 타입

    -키어트리뷰트 = 기본키 = primary key(PK)

    -관계(테이블 또는 릴레이션) : 흔히부르는 테이블이라는 이름으로 사용됨. 관계의 열은 어트리뷰트라고 하고, 행은 튜플이라고 부름

    -튜플(레코드 또는 행) : 관계를 구성하는 각각의 행

    -어트리뷰트(속성 또는 열)

    -도메인 : 어트리뷰트가 취할 수 있는 같은 타입의 원자 값들의 집합. 예를 들어 나이라는 어트리뷰트에서 나이  를 integer 타입의 0~150으로 정한다면 각각 나이들의 집합이 도메인 

    -후보키 :릴레이션에 이는 속성 중 유일성최소성을 만족하는 키로써, 후보키중 하나를 기본키로 사용함. 

    -기본키(primary key) : 후보키 중에서 선정된 하나로 유일성최소성을 만족함. 기본키는 null값과 중복값이 인정되지 않음.

    -슈퍼키 : 하나 이상의 어트리뷰트들의 합체로 이루어진 키. 

     예를 들어, 대학생 릴레이션에 이름과 학번이라는 어트리뷰트가 존재할 때 (이름+학번)을 하나의 키로 인정하고 사용함. 슈퍼키는 유일성을 가짐. (이름+학번)일 경우에 (이름+학번)이라는 키는 (학번)이라는 유일성을 가진 어트리뷰트 때문에 오직 하나만 존재할 것이기 때문. 

      그러나 슈퍼키는 최소성을 가지지 못함. 즉, (학번) 어트리뷰트만으로 각 튜플이 구분될 수 있는데, 굳이 학번에 이름을 합친(이름+학번)으로 해야하냐..

    -외래키(foreign key) : 다른 릴레이션의 어트리뷰트를 참조해 연결해 주는 어트리뷰트를 외래키라고 함. 이때 외래키는 다른 릴레이션의 유일성을 가진 애트리뷰트를 참조해야함. 학생 릴레이션의 소속학과 애트리뷰트가 학과 릴레이션의 학과번호 애트리뷰트를 참조할 때, 학생 릴레이션의 소속학과 애트리뷰트는 외래키가됨



    ・관계형 데이터베이스의 제약조건

    -★참조무결성 제약조건(referential integrity constraint) : 한 릴레이션에 있는 튜플이 다른 릴레이션에 있는 튜플을 참조하려면 반드시 참조되는 튜플이 해당 릴레이션 내에 존재해야 한다는 것.

     예를 들어, 학생 릴레이션의 소속학과 애트리뷰트에 5라는 튜플값이 존재한다고 하면, 이 외래키가 참조하는 학과 릴레이션의 학과번호 애트리뷰트에도 반드시 5가 존재해야한다.

    -키제약조건 : 키 어트리뷰트의 값은 릴레이션 내의 각 투플을 유일하게 식별할수 있어야 한다.

    -도메인 제약조건 : 각 애트리뷰트의 값은 반드시 도메인에 속하는 원자중 하나여야 한다.

    -엔티티 무결성 제약조건 : 어떠한 기본키 값도 null을 가질 수 없다.



    ・제약조건 위배에 따른 처리

    -삽입연산 : [201430010/곽나리/서울/5]를 학생 테이블에 넣고 싶은데, 참조하는 학과 테이블의 학과번호 애트리뷰트에서 5는 존재하지 않으므로 참조무결성 제약조건으로 인해 해당 데이터는 삽입될 수 없다.

    -삭제연산 : 학과 테이블에서 2번(게임공학과)를 삭제하려고하면, 학과 테이블의 학과번호 애트리뷰트를 참조하고 있는 테이블이 존재하고 있기 때문에 삭제되지 않는다.(삭제해버릴시 참조무결성 제약조건을 위배함)

    -수정연산 : 전요한의 소속학과를 5로 수정하려고 할 시 오류가 발생한다.

    + Recent posts