본문 바로가기

닷컴's_열공/Database

MySQL 의 주요 SQL 문법

이 부분은 MySQL 매뉴얼의 일부분을 중요하고 반드시 알아야 하는 부분 위주로 간략하게 정리한 것이며 모든 내용을 설명하고 있지는 않다. 실제 배포판에 포함되어 있는 매뉴얼은 600페이지 이상의 방대한 분량을 자랑하며 매우 알차게 만들어져 있다. 비록 영어로 되어 있지만 그리 어렵지 않으니 시간 날 때 틈틈이 읽어보면 많은 도움이 될 것이다. 부록 CD-ROM 의 /MySQL/manual 에 원문 매뉴얼이 포함 되어 있다.


4. MySQL 의 주요 SQL 문법

▶ CREATE DATABASE

문법 : CREATE DATABASE db_name

주어진 이름의 새로운 데이터베이스를 생성한다. 이때 사용 가능한 이름은 이 장의 첫 부분에서 설명한 바와 같다. 만일 같은 이름의 데이터베이스가 이미 존재 할 경우 에러가 난다. MySQL 은 데이터베이스를 디렉토리로 테이블을 파일로 관리하기 때문에 데이터베이스가 막 생성되었을 경우 테이블을 존재 하지 않으며 실제로 CREATE DATABASE 명령은 주어진 이름의 빈 디렉토리를 생성하는 역할을 한다.

다음과 같이 mysqladmin 유틸리티를 이용해서도 데이터베이스를 생성할 수 있다.
#./mysqladmin create school


▶DROP DATABASE

문법 : DROP DATABASE [IF EXISTS] db_name

DROP DATABASE 은 먼저 주어진 데이터베이스내의 모든 테이블을 삭제하고 데이터베이스를 삭제한다. 일단 삭제된 후에는 다시 복구 시킬 방법이 없으므로 사용에 주의해야 한다. 이 명령은 데이터베이스 디렉토리에 존재하던 파일의 수를 알려주는데 일반적으로 실제 존재하는 테이블 수의 3배이다. 이는 하나의 테이블이 인덱스 파일인`.ISD', 실제 데이터를 저장하는 `.ISM' 파일 그리고 테이블의 스키마(구조)를 저장하는 `.frm' 파일로 구성되어 있기 때문이다..

3.22 이후 버전부터 IF EXISTS 키워드가 추가 되었는데 이는 데이터베이스가 존재하지 않은 경우 에러가 발생하는 것을 막기 위해서 이다. 물론 mysqladmin 유틸리티를 이용해서도 데이터베이스를 삭제할 수 있다.
#./mysqladmin drop school


▶ CREATE TABLE : 테이블 생성

문법 : CREATE TABLE [IF NOT EXISTS] tbl_name (create_definition,...) [table_options] [select_statement]

 
create_definition:
  col_name type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT]
            [PRIMARY KEY] [reference_definition]
  or    PRIMARY KEY (index_col_name,...)
  or    KEY [index_name] KEY(index_col_name,...)
  or    INDEX [index_name] (index_col_name,...)
  or    UNIQUE [INDEX] [index_name] (index_col_name,...)
  or    [CONSTRAINT symbol] FOREIGN KEY index_name (index_col_name,...)
            [reference_definition]
  or    CHECK (expr)

type:
        TINYINT[(length)] [UNSIGNED] [ZEROFILL]
  or    SMALLINT[(length)] [UNSIGNED] [ZEROFILL]
  or    MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL]
  or    INT[(length)] [UNSIGNED] [ZEROFILL]
  or    INTEGER[(length)] [UNSIGNED] [ZEROFILL]
  or    BIGINT[(length)] [UNSIGNED] [ZEROFILL]
  or    REAL[(length,decimals)] [UNSIGNED] [ZEROFILL]
  or    DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL]
  or    FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL]
  or    DECIMAL(length,decimals) [UNSIGNED] [ZEROFILL]
  or    NUMERIC(length,decimals) [UNSIGNED] [ZEROFILL]
  or    CHAR(length) [BINARY]
  or    VARCHAR(length) [BINARY]
  or    DATE
  or    TIME
  or    TIMESTAMP
  or    DATETIME
  or    TINYBLOB
  or    BLOB
  or    MEDIUMBLOB
  or    LONGBLOB
  or    TINYTEXT
  or    TEXT
  or    MEDIUMTEXT
  or    LONGTEXT
  or    ENUM(value1,value2,value3,...)
  or    SET(value1,value2,value3,...)

index_col_name:
        col_name [(length)]

reference_definition:
        REFERENCES tbl_name [(index_col_name,...)]
                   [MATCH FULL | MATCH PARTIAL]
                   [ON DELETE reference_option]
                   [ON UPDATE reference_option]

reference_option:
        RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT

table_options:
    type = [ISAM | MYISAM | HEAP]
or    max_rows = #
or    min_rows = #
or    avg_row_length = #
or    comment = "string"
or    auto_increment = #

select_statement:
    [ | IGNORE | REPLACE] SELECT ...  (Some legal select statement)



CREATE TABLE 은 현재 사용중인 데이터베이스에 새로운 테이블을 만든다. 만일 데이터베이스가 선택되지 않았거나 같은 이름의 테이블이 존재하면 에러가 발생한다.

MySQL 3.22 이후 버전부터는 테이블 이름을db_name.tbl_name 과 같이 지정해 줄 수 있게 되어 선택된 데이터베이스가 없어도 된다. 또한 3.23 버전부터는 IF NOT EXISTS 키워드를 제공해 이를 사용할 경우 테이블이 존재 하지 않을 경우만 생성하며 이미 존재하더라고 에러가 발생하지 않는다.

각각의 테이블 tbl_name 은 해당 데이터베이스의 디렉토리에 다음과 같은 3가지 파일로 존재한다.

파일명 기능
tbl_name.frm 테이블 구조 정의 파일
tbl_name.ISD 데이터 파일
tbl_name.ISM 인덱스 파일
 

  • 만일 NULL 이나 NOT NULL로 정의되지 않은 컬럼은 자동적으로 NULL 컬럼으로 만들어 진다.
  • BLOB 과 TEXT 컬럼은 NOT NULL 로 지정해도 항상 NULL 로 정의된다. 정수형 컬럼은 AUTO_INCREMENT 키워드를 사용할 수 있다. AUTO_INCREMENT로 정의된 컬럼에 NULL또는 0을 입력할 경우 해당 컬럼의 최대값보다 1만큼 증가된 값이 입력된다. AUTO_INCREMENT 컬럼은 1 부터 시작한다. 만일 최대 값을 가진 행이 삭제 될 경우 그 값은 새로이 입력되는 행에 다시 사용된다. 하나의 테이블에는 단 하나의 AUTO_INCREMENT 컬럼만이 사용가능하며 반드시 인덱스로 정의되어야 한다.
  • 만일 DEFAULT 옵션이 사용되지 않은 경우 해당 컬럼이 NULL 컬럼이면 NULL 값이 NOT NULL 컬럼이면 다음 중 한가지 값이 자동적으로 지정된다.
    • AUTO_INCREMENT 이 아닌 숫자형 컬럼이면 0
    • TIMESTAMP 타입이 아닌 날짜형 컬럼이면 해당 타입의 제로 값(zero value)
    • 문자형 컬럼은 빈 문자열
  • UNIQUE 컬럼은 각 행이 다른 값을 가져야만 한다. 만일 기존의 값과 같은 행이 입력될 경우 오류가 에러가 발생한다.,
  • KEY 는 INDEX의 또 다른 이름이다.
  • PRIMARY KEY 는 다중 컬럼을 사용할 수 있다. 단 컬럼 정의 뒷부분에서는 사용할 수 없고 PRIMARY KEY(index_col_name, ...) 과 같이 또 다른 줄로 써야 한다.
  • 만일 인덱스에 이름을 지정해 주지 않을 경우 첫번째 인덱스 컬럼에 숫자를 붙인 형태로 자동으로 만들어진다,
  • 인덱스 컬럼은 NULL 키워드를 사용할 수 없다. 따라서 NOT NULL 을 선언하지 않으면 에러가 발생한다
  • BLOB and TEXT columns cannot be indexed.
  • CHAR 또는 VARCHAR 컬럼의 일부만을 col_name(length)와 같은 방식으로 인덱스 하면 인덱스 파일의 크기가 작아진다.
  • TEXT 또는 BLOB 컬럼에 ORDER BY 혹은 GROUP BY 구문을 사용할 경우 컬럼 앞부분에서 max_sort_length 변수에 정의된 길이까지만 사용된다. FOREIGN KEY, CHECK , REFERENCES 구문은 타 데이터베이스와의 호환을 위해서만 존재 하며 실제로는 아무런 작용도 하지 않느다.

    ▶ ALTER TABLE

    문법 : ALTER [IGNORE] TABLE tbl_name alter_spec [, alter_spec ...]

     
    alter_spec:
            ADD [COLUMN] create_definition [FIRST | AFTER column_name ]
      or    ADD INDEX [index_name] (index_col_name,...)
      or    ADD PRIMARY KEY (index_col_name,...)
      or    ADD UNIQUE [index_name] (index_col_name,...)
      or    ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}
      or    CHANGE [COLUMN] old_col_name create_definition
      or    MODIFY [COLUMN] create_definition
      or    DROP [COLUMN] col_name
      or    DROP PRIMARY KEY
      or    DROP INDEX key_name
      or    RENAME [AS] new_tbl_name
      or    table_option
    



    ALTER TABLE 명령은 만들어진 테이블의 구조를 변경 할 수 있게 해준다. 예를 들어 컬럼을 추가하거나 삭제, 변경 할 수 있고 인덱스를 생성하거나 삭제할 수도 있다

    ALTER TABLE 명령은 원래 테이블을 임시 테이블로 복사해 변경사항을 적용하고 새로운 테이블의 이름을 변경하고 원래 테이블을 삭제하게 된다. 이렇게 함으로서 테이블의 구조를 변경하는 동안에 발생하는 업데이트도 실패 없이 이루어 진다. 새로이 변경된 테이블이 준비될 때까지 쓰기와 갱신은 잠시 지연되게 된다.

     

  • ALTER TABLE 명령을 사용하기 위해서는 테이블에 대한 select, insert, delete, update, create , drop 권한이 있어야 한다.
  • IGNORE 키워드는 MySQL의 확장기능이다. 이를 사용하면 인덱스 컬럼에 존재하는 데이터에 따른 제어가 가능하다 즉 IGNORE를 사용하면 테이블 변경에 따른 인덱스 컬럼에 존재하는 인덱스 컬럼이 같은 모든 행이 첫번째 행을 제외하고 삭제 된다.
  • 여러 가지의 ADD, ALTER, DROP , CHANGE 구문을 하나의 ALTER TABLE 명령 안에서 사용가능하다
  • CHANGE col_name, DROP col_name , DROP INDEX 는 MySQL 의 확장 기능이다.
  • MODIFY 는 ALTER TABLE에 대한 Oracle 의 확장기능이다.
  • COLUMN 키워드는 생략 가능하다
  • 아무런 옵션 없이 ALTER TABLE tbl_name RENAME AS new_name 구문을 이용하면 간단히 테이블 이름을 바꿀 수 있다.
  • CHANGE old_col_name create_definition 문을 이용해서도 컬럼 명을 변경할 수 있다. 이때 이전 컬럼명과 새로운 컬럼명 그리고 컬럼의 타입을 써주면 된다. 예를 들어 a 라는 INTEGER 컬럼을 b 라는 이름으로 바꾸려면 다음과 같이 한다.
    mysql> ALTER TABLE t1 CHANGE a b INTEGER;

    만일 컬럼의 이름은 변경하지 않고 타입만을 바꾸려면 같은 이름을 두 번 연속해서 써주면 된다, 이는 이전이름과 새로운 이름이 같다는 의미이다.
    mysql> ALTER TABLE t1 CHANGE b b BIGINT NOT NULL;

    MySQL 3.22.16 이후 버전부터는 MODIFY 구문을 지원해 새로운 이름을 지정하지 않고 다음과 같이 컬럼 명을 변경할 수 있게 되었다.
    mysql> ALTER TABLE t1 MODIFY b BIGINT NOT NULL;

     
  • 만일 CHANGE 또는 MODIFY 을 이용해 컬럼의 일부부만이 인덱스가 걸린 컬럼의 길이를 줄이려 할 경우 그 인덱스의 크기이하로는 작게 변경할 수 없다.
  • DROP INDEX 는 인덱스를 제거한다. 이는 ANSI SQL92에서는 지원하지 않는 MySQL 확장기능이다
  • 만일 인덱스로 잡혀있는 컬럼이 삭제되면 그 컬럼에 만들어진 인덱스 역시 자동적으로 지원진다.
  • DROP PRIMARY KEY 는 기본 키 인덱스를 제거한다. 만일 기본 키가 없을 경우에는 테이블의 가장 앞부분에 존재하는 UNIQUE 인덱스를 지운다.
  • FOREIGN KEY, CHECK REFERENCES 옵션은 실제로 아무런 동작도 하지 않는다. 이 러한 것들은 단지 호환성을 위해 존재 할 뿐이다. 아래에 ALTER TABLE 의 사용에 대한 몇 가지 예가 있다.

    일단 테이블 t1 을 생성한다 .
    mysql> CREATE TABLE t1 (a INTEGER,b CHAR(10));

    테이블 t1 의 이름을 t2로 변경한다.
    mysql> ALTER TABLE t1 RENAME t2;

    컬럼a를 INTEGER에서 TINYINT NOT NULL로 컬럼 타입만을 바꾸고 CHAR(10) 컬럼b를 CHAR(20)의 c 라는 이름으로 바꿔본다.
    mysql> ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);

    d 라는 새로운 TIMESTAMP 컬럼을 추가 한다.
    mysql> ALTER TABLE t2 ADD d TIMESTAMP;

    컬럼 d 에 인덱스를 생성하고 컬럼 a를 기본 키로 만든다.
    mysql> ALTER TABLE t2 ADD INDEX (d), ADD PRIMARY KEY (a);

    컬럼 c 를 제거한다.
    mysql> ALTER TABLE t2 DROP COLUMN c;

    AUTO_INCREMENT 컬럼c를 추가한다. 이때 AUTO_INCREMENT 컬럼은 NOT NULL 이며 인덱스가 생성되어야만 한다는 사실에 주의 하자.
    mysql> ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT, ADD INDEX (c);

    ▶ OPTIMIZE TABLE

    문법 : OPTIMIZE TABLE tbl_name

    OPTIMZE TABLE 은 테이블에서 상당의 자료를 삭제 했거나 VARCHAR, BLOB , TEXT 등과 같은 가변폭 컬럼에 많은 변화가 생겼을 경우 사용된다. 삭제된 자료는 링크된 공간으로 남고 뒤따른 INSERT 명령에 의해 재사용되므로 저장공간은 불연속 적으로 된다. OPTIMIZE TABLE 명령은 사용되지 않은 공간을 반환하게 한다.

    OPTIMIZE TABLE 은 원본 테이블의 복사본을 만들어 작업을 하게 된다. 이전 테이블이 사용되지 않은 공간을 정리해 새로운 테이블이 만들어지면 이전 테이블은 삭제되고 임시 테이블의 이름이 삭제된 테이블과 같이 변경된다. 이런 방식으로 인해 모든 업데이트는 성공적으로 수행되며 OPTIMIZE TABLE 명령이 실행되고 있는 도중에도 원래의 테이블은 읽기가 가능하며 업데이트 및 데이터의 쓰기는 새로 만들어진 테이블이 준비될 때까지 잠시 지연 된다.


    ▶ DROP TABLE

    문법 : DROP TABLE [IF EXISTS] tbl_name [, tbl_name,...]

    DROP TABLE 은 하나 이상의 테이블을 삭제한다. 테이블 내의 모든 데이터와 테이블의 구조에 대한 정의가 순식간에 사라지니 사용에 주의해야 한다. MySQL 3.22 이후 버전부터 IF EXISTS 키워드가 추가 되어 테이블이 존재 하지 않은 경우 생기는 오류를 막을 수 있게 되었다.

    ▶ DELETE

    문법 : DELETE [LOW_PRIORITY] FROM tbl_name [WHERE where_definition] [LIMIT rows]

    DELETE 는 주어진 조건에 맞는 행을 삭제한 후 삭제 된 행의 수를 리턴한다.

    만일 WHERE 조건 절을 생략하면 모든 행이 삭제 된다. 이 경우 MySQL 은 먼저 같은 이름의 빈 테이블을 새롭게 만드는데 이 방법이 각각의 행을 지우는 것보다 빠르기 때문이다. 이때 지워진 행의 수는 0 을 리턴한다.

    만일 시간이 좀더 걸리더라도 몇 개의 행이 삭제 되었는지 알고 싶다면 WHERE 절을 생략하지 말고 다음과 같이 항상 참인 내용을 적어 주면 된다.
    mysql> DELETE FROM tbl_name WHERE 1>0;

    이 경우 당연히 WHERE 절을 생략한 채 모두 지우는 것보다 훨씬 느리게 된다.
    만일 LOW_PRIORITY 키워드를 사용하면 모든 사용자가 해당 테이블의 사용을 끝낼 때까지 DELETE 의 실행이 지연된다.

    지워진 데이터 영역은 새롭게 추가 되는 데이터들에 의해 불연속적으로 채워지게 되므로 OPTIMIZE TABLE 명령과 isamchk 유틸리티를 이용하면 속도가 향상된다. OPTIMIZE TABLE 은 사용이 쉬운 반면 isamchk 유틸리티는 복구 속도가 빠르다 .

    MySQL에서만 사용이 가능한 LIMIT 키워드를 사용해 한번에 삭제할 행의 수를 지정해 줄수 있다. 이는 얼마나 많은 자료가 삭제될지 예측할 수 없는 경우 시간절약을 위해 사용될 수 있다. 물론 LIMIT를 반복해서 사용하면 조건에 맞는 모든 자료를 삭제 할 수 있다.

    ▶SELECT

    문법 : SELECT [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [DISTINCT | ALL]

     
    select_expression,...
        [INTO OUTFILE 'file_name' export_options]
        [FROM table_references
            [WHERE where_definition]
            [GROUP BY col_name,...]
            [HAVING where_definition]
            [ORDER BY {unsigned_integer | col_name} [ASC | DESC] ,...]
            [LIMIT [offset,] rows]
            [PROCEDURE procedure_name] ]
    



    SELECT 는 하나 이상의 테이블에서 데이터를 가져올 때 사용 된다.
    select_expression 은 데이터를 가져올 컬럼을 나타낸다. SELECT 문을 테이블의 컬럼이 아닌 단순한 연산이나 함수의 결과를 나타낼 때에도 사용된다. 아래의 예를 보자.

     

    mysql> SELECT 1 + 1;
    -> 2
    



    모든 키워드는 위의 사용법에 나온 순서대로 나와야 한다. 예를 들어 HAVING 절은 반드시 GROUP BY 뒤와ORDER BY 사이에 나와야만 한다.

     

  • AS를 이용해 컬럼명을 별명(alias)으로 쓸 수 있다. 별명은 ORDER BY 또는 HAVING 절에서도 사용가능하다.
    mysql> select concat(last_name,', ',first_name) AS full_name from mytable ORDER BY full_name;

     
  • FROM table_references 는 데이터를 가져올 테이블을 나타낸다. 만일 두개 이상의 테이블을 이용할 경우는 조인을 해야만 할 것이다.
     
  • 컬럼명은col_name, tbl_name.col_name , db_name.tbl_name.col_name 과 같은 방법으로 참조 할 수 있다 . 그러나 두개 이상의 테이블에서 공통적으로 존재하는 컬럼을 사용하는 경우가 아니라면 생략해도 무방하다.
     
  • 데이터의 정렬을 위해 ORDER BY , GROUP BY 절에서는 컬럼명 , 컬럼의 별명, 컬럼 인덱스(1부터 시작)를 사용할 수 있다.

     
    mysql> select college, region, seed from tournament
               ORDER BY region, seed;
    mysql> select college, region AS r, seed AS s from tournament
               ORDER BY r, s;
    mysql> select college, region, seed from tournament
               ORDER BY 2, 3;
    



    내림차순으로 정렬하기 위해서는 DESC 키워드를 사용하다. 오름차순으로 정렬하기 위해서는 ASC 키워드를 사용하는데 디폴트로 되어 있으므로 생략이 가능하다.

     

  • HAVING 절은 select_expression 에 나온 컬럼, 컬럼의 별명 등을 참조 할 수 있다. 이 절은 데이터를 출력하기 직전에 가장 마지막으로 처리된다. 따라서 HAVING절 내에는 WHERE에서 사용해야 할 컬럼을 쓰면 안된다. 아래 잘못된 예가 있다.
    mysql> select col_name from tbl_name HAVING col_name > 0;

    다음과 같이 써야만 한다.
    mysql> select col_name from tbl_name WHERE col_name > 0;

    MySQL 3.22.5 이후 버전에서는 다음과 같이 쓸 수도 있다.
    mysql> select user,max(salary) from users group by user HAVING max(salary)>10;

    구 버전인 경우에는 대신 다음과 같이 써야 한다:
    mysql> select user,max(salary) AS sum from users group by user HAVING sum>10;

     
  • LIMIT 절은 SELECT 문에 의해 나타나는 데이터의 개수를 조절할 수 있게 해 준다. LIMIT 는 하나 또는 두개의 인자를 가질 수 있다. 만일 두개의 인자가 사용되면 앞의 인자는 건너뛸 행의 수를 나타낸다. 뒤의 인자는 최대로 가져올 행의 수이다. 인자가 하나만 사용될 경우 첫번째 인자가 0 이라 간주되고 주어진 값 만큼의 행을 가져오게 된다. 다시 말해 LIMIT n 은 LIMIT 0,n. 과 같은 의미이다.
     
    mysql> select * from table LIMIT 5,10;  # 6-15 행까지
    If one argument is given, it indicates the maximum number of rows to return. 
    mysql> select * from table LIMIT 5;     # 처음 5 행
    



    SELECT ... INTO OUTFILE 'file_name' 는 가져온 데이터를 파일에 저장한다, 이때 파일은 서버에 만들어 지며 같은 이름의 파일이 이미 존재해서는 안된다. 또한 사용자는 반드시 file 권한을 가지고 있어야만 한다 .

    ▶ JOIN

    MySQL 은 SELECT 문 내에서 아래와 같은 JOIN 문을 지원한다.

    문법 : table_reference, table_reference
    table_reference [CROSS] JOIN table_reference
    table_reference STRAIGHT_JOIN table_reference
    table_reference LEFT [OUTER] JOIN table_reference ON conditional_expr
    table_reference LEFT [OUTER] JOIN table_reference USING (column_list)
    table_reference NATURAL LEFT [OUTER] JOIN table_reference
    { oj table_reference LEFT OUTER JOIN table_reference ON conditional_expr }
    마지막의 LEFT OUTER JOIN 구문은 ODBC 호환을 위해존재 한다.

     

  • 테이블 참조는 tbl_name AS alias_name 또는 tbl_name alias_name 과 같은 방식으로 할 수 있다.
    mysql> select t1.name, t2.salary from employee AS t1, info AS t2 where t1.name = t2.name;

     
  • ON 조건은 WHERE 절에서 사용되는 내용이 올 수 있다.
     
  • 만일 LEFT JOIN에 의해 오른편 테이블에 조건에 맞는 자료가 없을 때에는 오른펴 테이블의 모든 컬럼이 NULL인 가상의 행으로 처리된다. 이러한 특징을 이용해 하나의 테이블에만 존재하는 자료의 수를 구할 수 있다.

    mysql> select table1.* from table1 LEFT JOIN table2 ON table1.id=table2.id where table2.id is NULL; 위의 예는 table1 에 있는 자료 중에 id 값이 table2 에는 존재하지 않는 자료를 모두 가져온다.

     
  • USING column_list 절에서 사용되는 컬럼명은 반드시 양쪽 테이블에 모두 존재해야 한다. 아래 예를 보자:

    A LEFT JOIN B USING (C1,C2,C3,...)

    이 문장은 다음과 같이 쓸 수도 있다.
    A.C1=B.C1 AND A.C2=B.C2 AND A.C3=B.C3,...

    그 밖에 몇가지 예를 살펴보면 아래와 같다.
    mysql> select * from table1,table2 where table1.id=table2.id;
    mysql> select * from table1 LEFT JOIN table2 ON table1.id=table2.id;
    mysql> select * from table1 LEFT JOIN table2 USING (id);
    mysql> select * from table1 LEFT JOIN table2 ON table1.id=table2.id LEFT JOIN table3 ON table2.id=table3.id;


    ▶ INSERT

    문법 : INSERT [LOW_PRIORITY | DELAYED] [IGNORE] [INTO] tbl_name [(col_name,...)] VALUES (expression,...),(...),... or INSERT [LOW_PRIORITY | DELAYED] [IGNORE] [INTO] tbl_name [(col_name,...)] SELECT ...or INSERT [LOW_PRIORITY | DELAYED] [IGNORE] [INTO] tbl_name SET col_name=expression, col_name=expression, ...
    INSERT 테이블에 새로운 행을 삽입한다.
    The INSERT ... SELECT 구문은 다른 테이블에서 SELECT 된 데이터를 입력할 때 사용된다. tbl_name 은 행이 삽입될 테이블 명이다. 컬럼명이나 SET 절은 데이터가 삽입될 컬럼을 지정해 준다.

     
  • 만일 INSERT ... VALUES 또는 INSERT ... SELECT 구문 내에 컬럼이 지정되지 않았다면 모든 컬럼에 각각 해당되는 데이터가 VALUES() 또는 SELECT 문에 의해 제공되어야 한다. 만일 테이블내의 컬럼의 순서를 모를 경우 DESCRIBE tbl_name 을 이용하면 쉽게 알 수 있다.
     
  • expression 부분은 앞서 VALUES 리스트에 나온 값을 이용할 수 있다. 다음 예를 보자.
    mysql> INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);

    그러나 다음의 경우는 오류가 발생한다. 반드시 앞쪽에 나온 값만을 참조 할수 있다는 것을 주의하기 바란다.
    mysql> INSERT INTO tbl_name (col1,col2) VALUES(col2*2,15);
     
  • 만일LOW_PRIORITY 키워드를 사용하면 다른 모든 사용자가 사용중인 테이블에서 읽기 작업을 끝낼 때까지 INSERT 문의 실행이 지연된다.
     
  • IGNORE 키워드를 사용하면 새로 삽입되는 데이터와 같은 키(PRIMARY 또는 UNIQUE key) 값을 갖는 데이터는 무시되고 다음 데이터가 입력된다. 만일 IGNORE 를 사용하지 않을 경우에는 INSERT 의 실행이 중단되어 버린다. 이때 mysql_info() 함수를 이용하면 테이블에 얼마나 많은 행이 삽입되었는지 알 수 있다.
     
  • NOT NULL 컬럼에 NULL 이 입력될 경우 무시되고 디폴트 값으로 입력된다.
     
  • 숫자형 컬럼에 사용범위를 벗어나는 값이 입력될 경우 표시 가능한 가장 가까운 수로 변경되어 삽입된다.
     
  • CHAR, VARCHAR, TEXT , BLOB 컬럼에 최대 입력 자리보다 큰 데이터가 들어올 경우 표시 가능한 부분까지만 잘려서 입력된다.
     
  • 날짜 컬럼에 적절하지 못한 값이 입력되면 제로 값(zero value)으로 입력된다.
    DELAYED 옵션은 INSERT 문의 실행을 기다릴 수 없는 사용자가 있을 경우에 매우 유용하다. 이 경우 만일 SELECT 문을 사용하는 사용자가 있을 경우 우선권을 주어 먼저 실행시키고 나서 INSERT 문의 실행을 처리 하게 된다. 이것은 ANSI SQL92 에는 없는 MySQL 의 확장 기능이다.
    DELAYED 옵션의 또 다른 장점은 많은 사용자들에 의해 INSERT가 일어날 때 이들에 의해 삽입될 데이터를 모아서 한꺼번에 쓰기 작업을 한다는 것이다. 이 경우 각각의 데이터를 삽입할 때 보다 작업 속도가 빠르다.

    ▶ REPLACE

    문법 : REPLACE [LOW_PRIORITY | DELAYED] [INTO] tbl_name [(col_name,...)] VALUES (expression,...) or REPLACE [LOW_PRIORITY | DELAYED] [INTO] tbl_name [(col_name,...)] SELECT ... or REPLACE [LOW_PRIORITY | DELAYED] [INTO] tbl_name SET col_name=expression, col_name=expression,... REPLACE 명령은 INSERT 명령과 유사하게 동작하나 한가지 차이점은 인덱스 컬럼에 기존의 값과 같은 행이 입력될 경우 기존의 행을 삭제하고 새로운 행의 입력이 이루어진다.

    ▶ LOAD DATA INFILE

    문법 : LOAD DATA [LOCAL] INFILE 'file_name.txt' [REPLACE | IGNORE] INTO TABLE tbl_name [FIELDS [TERMINATED BY '\t'] [OPTIONALLY] ENCLOSED BY "] [ESCAPED BY '\\' ]] [LINES TERMINATED BY '\n'] [IGNORE number LINES] [(col_name,...)] LOAD DATA INFILE 명령은 텍스트 파일에서 데이터를 읽어 매우 빠른 속도로 테이블에 입력해 준다. LOCAL 키워드를 사용할 경우 클라이언트의 호스트에 존재하는 파일을 사용하고 그렇지 않은 경우 MySQL이 구동중인 서버에 존재하는 파일이 사용된다. 서버에 존재하는 파일을 이용 LOAD DATA INFILE 명령을 실행하기 위해서는 file 권한을 가지고 있어야 하며 보안상의 이유로 서버에 존재하는 파일을 읽을 경우 해당 데이베이스의 디렉토리에 존재하거나 아무나 읽을 수 있는 퍼미션을 가지고 있어야 한다.

    서버에 존재하는 파일을 이용하기 위해 다음의 규칙이 있다.
     
  • 절대경로로 주어질 경우 패스이름을 그대로 따른다
  • 만일 상대 경로가 주어질 경우 사용중인 데이터베이스의 디렉토리에 대한 상대경로로 인식한다.
  • 경로 없이 파일이름만 사용하면 사용중인 데이터베이스의 디렉토리에서 파일을 찾으려 한다

    REPLACE 및 IGNORE 키워드는 인덱스 컬럼에 입력되는 데이터 행을 제어한다. 만일 REPLACE 를 사용할 경우 기존의 행은 삭제 되고 새로운 값이 입력되며,IGNORE 를 사용 할경우 새로운 값은 무시되고 기존의 값이 보존된다. 만일 키워드가 없으면 오루가 발생한다.

    FIELDS 키워드를 사용할 경우 TERMINATED BY, [OPTIONALLY] ENCLOSED BY , ESCAPED BY 선택 사항 중 반드시 한가지 이상 사용해야 하며 만일 FIELDS 키워드를 사용하지 않을 경우 기본값은 다음 명령을 내린 것과 같다.
    FIELDS TERMINATED BY '\t' ENCLOSED BY " ESCAPED BY '\\'

    LINES 키워드를 사용하지 않을 경우 기본값은 다음 명령을 내린 것과 같다.
    LINES TERMINATED BY '\n'

    다시 말해 LOAD DATA INFILE 명령의 기본 값은 다음과 같다
     
  • 각각의 행은 리턴값( newline )으로 구분된다.
  • 각 컬럼은 탭으로 구분된다.
  • 각 데이터는 인용부호를 사용하지 않는다.
  • 줄이 바뀌는 경우 `\'문자를 사용한다 ▶ UPDATE

    문법 : UPDATE [LOW_PRIORITY] tbl_name SET col_name1=expr1,col_name2=expr2,... WHERE where_definition] UPDATE 명령은 테이블내의 각 컬럼의 값을 새로운 값으로 갱신한다. SET 구문은 변경될 컬럼과 새로운 값을 지정해 준다. 만일 WHERE 구문이 주어질 경우 조건을 만족시키는 행만 갱신되며 생략되면 모든 행이 갱신된다.

    LOW_PRIORITY 옵션이 사용되면 다른 모든 클라이언트가 해당 테이블에 대한 읽기 작업이 끝날 때까지 UPDATE 의 실행이 지연된다.

    SET 구문에서 테이블의 컬럼명을 사용할 경우 해당 컬럼에 저장되어 있는 값이 사용된다 아래의 age 컬럼을 현재의 값보다 1만큼 증가 시키는 예이다.
    mysql> UPDATE persondata SET age=age+1;

    UPDATE 문은 각각의 연산을 왼쪽에서 오른쪽으로 실행한다. 아래의 age 컬럼을 현재 값의 2배 한 후 1만큼 증가 시키는 예이다.

    mysql> UPDATE persondata SET age=age*2, age=age+1;

    잠깐!: 만일 현재 값과 같은 값으로 갱신한다면 MySQL 이를 무시하고 실행하지 않는다.

    ▶ USE

    문법 : USE db_name

    USE 명령은 사용할 데이터베이스를 변경한다.

    mysql> USE db1;
    mysql> SELECT count(*) FROM mytable; # selects from db1.mytable
    mysql> USE db2;
    mysql> SELECT count(*) FROM mytable; # selects from db2.mytable
    USE 명령으로 특정 데이터베이스를 사용하더라도 데이터베이스이름을 지정해 주면 다른 데이터베이스에 존재하는 테이블을 사용할 수 있다.

    아래 예는 데이터베이스 db1 에 존재하는 author 테이블과 db2 데이터베이스 내의 editor 테이블을 사용하는 것을 보여준다.
    mysql> USE db1;
    mysql> SELECT author_name,editor_name FROM author,db2.editor WHERE author.editor_id = db2.editor.editor_id;
    USE 명령은 Sybase 와의 호환을 위해 제공된다.

    ▶ FLUSH

    문법 : FLUSH flush_option [,flush_option]

    MySQL 에 의해 사용되는 내부 캐시를 지우고 새로 읽어 들이기 위해 사용되는 명령이다. 이 명령을 사용하기 위해서는 reload 권한을 가지고 있어야 한다.

    flush_option 에는 아래와 같은 옵션이 있다.

     
    옵션 설명
    HOSTS host 테이블을 다시 읽어 들인다. 접속하려는 호스트의 IP 가 변경 되었거나 새로운 호스트를 추가 했을 경우 그리고 "Host ... is blocked" 에러 메시지나 나타나면 host 테이블을 다시 읽어 들여야만 한다. 최대 접속 가능 수보다 더 많은 호스트들이 접속을 시도할 경우 에러(max_connect_errors)가 발생하고 이 때 MySQL 은 뭔가 잘 못되었음을 판단하고 host 테이블에 등록된 호스트조차 더 이상의 접속을 거부하게 된다. 이러한 에러를 방지하기 위해서는 아래 같이 매우 큰 값을 지정해서 데몬을 띄우면 된다.
    shell> mysqld -O max_connection_errors=999999999
    LOGS 로그파일을 비우고 새롭게 생성한다. 만일 로그파일 이름을 확장자 없이 지정해 주면 자동적으로 이전 로그파일의 이름에 1 이 증가된 파일명이 생긴다.
    PRIVILEGES mysql 데이터베이스내의 권한 관리 테이블을 다시 읽어 들인다.
    TABLES 열려진 모든 테이블을 닫는다.
    STATUS 모든 상태 변수(status variables)를 0으로 만든다


    아래와 같이 mysqladmin 유틸리티를 이용해도 같은 작업을 할 수 있다.
    shell> mysqladmin flush-hosts, flush-logs, reload , flush-tables

    ▶ KILL

    문법 : KILL thread_id

    mysqld 에 의해 각각의 접속은 독립적인 쓰레드로 운영된다. SHOW PROCESSLIST 명령에 의해 동작중인 쓰레드를 볼 수 있고 KILL thread_id 명령에 의해 쓰레드를 죽일 수 있다. PROCESS 권한을 가지고 있을 경우 모든 쓰레드를 볼 수 있고 그렇지 않으면 자신의 쓰레드만을 볼 수 있다.

    아래와 같은 방법으로 쓰레드를 점검하고 죽일 수 있다.
    shell >mysqladmin processlist 와 shell > mysqladmin kill thread_id

    ▶ SHOW

    테이블 , 컬럼 및 기타 정보를 보여준다.

    문법 : SHOW DATABASES [LIKE wild] or SHOW TABLES [FROM db_name] [LIKE wild] or SHOW COLUMNS FROM tbl_name [FROM db_name] [LIKE wild] or SHOW INDEX FROM tbl_name [FROM db_name] or SHOW STATUS or SHOW VARIABLES [LIKE wild] or SHOW PROCESSLIST or SHOW TABLE STATUS [FROM db_name] [LIKE wild]

    SHOW 명령은 데이터베이스, 테이블 ,컬럼 , MySQL서버 에 대한 정보를 보여 준다. LIKE 문을 사용하면 `%' 와 `_' 와일드 카드 문자를 사용할 수 있다

    db_name.tbl_name 을 tbl_name FROM db_name 과 같은 형식으로 사용 할 수 있다. 따라서 아래 두 문장은 같은 기능을 한다.
    mysql> SHOW INDEX FROM mytable FROM mydb;
    mysql> SHOW INDEX FROM mydb.mytable;


    SHOW DATABASES - MySQL 서버 호스트에 존재하는 데이터베이스 목록을 보여준다. 쉘 프롬프트 상에서의mysqlshow 명령도 같은 기능을 한다.

    SHOW TABLES - 선택된 데이터베이스 내에 존재하는 테이블을 보여준다. 쉘 프롬프트 상에서의 mysqlshow db_name 과 같다.

    주의: 만일 테이블에 대한 권한이 아무것도 없다면 결과가 나타나지 않는다.

    SHOW COLUMNS 테이블에 있는 컬럼 정보를 보여준다. DESCRIBE 명령도 비슷한 역할 을 한다.

    SHOW TABLE STATUS - 3.23 버전에서 추가된 기능이다. SHOW STATUS 와 비슷한 기능을 하지만 각각의 테이블에 대한 상세한 정보를 얻을 수 있다. 쉘 프롬프트 상에서 mysqlshow --status db_name 명령을 통해서도 같은 결과를 얻을 수 있다.

    아래와 같은 정보가 보여진다.
     

    항 목 설 명
    Name 테이블 이름
    Type 테이블 타입 (NISAM, MYISAM, HEAP)
    Rows 열의 수
    Avg_row_length 열의 평균 길이
    Data_length 데이터 파일의 크기
    Max_data_length 데이터 파일의 최대 크기
    Index_length 인덱스 파일의 크기
    Data_free 데이터 파일에 할당되었지만 사용되지 않은 공간의 크기
    Auto_increment Auto_increment 컬럼의 다음 값
    Create_time 테이블의 생성 시간
    Update_time 테이블의 마지막 수정 시간
    Check_time 테이블을 마지막 점검한 시간
    Create_min_rows 테이블 생성시 "min_rows" 옵션 사용 여부
    Create_max_rows 테이블 생성시 "max_rows" 옵션 사용 여부
    Create_avg_row_length 테이블 생성시 "avg_row_length" 옵션 사용 여부
    Comment 테이블 생성시 입력한 주석



    SHOW FIELDS - SHOW COLUMNS 또는 SHOW KEYS 와 같다 테이블의 컬럼이나 인덱스 정보를 보여준다.

    SHOW INDEX - 아래와 같은 인덱스 정보를 보여준다

     

    항 목 설 명
    Table 테이블 이름
    Non_unique 인덱스에 동일한 값이 저장되지 않는다면 0
    Key_name 인덱스 이름
    Seq_in_index 인덱스 내의 몇 번째 컬럼 인가 1부터 시작.
    Column_name 컬럼 이름
    Collation 인덱스가 어떻게 저장되나. A (오름차순 정렬) , NULL (정렬안됨).
    Cardinality 인덱스 내에 존재하는 유일한 데이터의 수
    Sub_part 컬럼 일부만을 인덱스하는 경우 이 크기. 만일 컬럼 전체가 사용되면 NULL



    SHOW STATUS - 서버의 상태에 대한 정보를 보여준다. 쉡 프롬프트 상태에서의 mysqladmin extended-status 명령과 같다. 결과 값은 아래와 비슷할 것이다.

     

    +--------------------------+--------+
    | Variable_name            | Value  |
    +--------------------------+--------+
    | Aborted_clients          | 0      |
    | Aborted_connects         | 0      |
    | Created_tmp_tables       | 0      |
    | Delayed_insert_threads   | 0      |
    | Delayed_writes           | 0      |
    | Delayed_errors           | 0      |
    | Flush_commands           | 2      |
    | Handler_delete           | 2      |
    | Handler_read_first       | 0      |
    | Handler_read_key         | 1      |
    | Handler_read_next        | 0      |
    | Handler_read_rnd         | 35     |
    | Handler_update           | 0      |
    | Handler_write            | 2      |
    | Key_blocks_used          | 0      |
    | Key_read_requests        | 0      |
    | Key_reads                | 0      |
    | Key_write_requests       | 0      |
    | Key_writes               | 0      |
    | Max_used_connections     | 1      |
    | Not_flushed_key_blocks   | 0      |
    | Not_flushed_delayed_rows | 0      |
    | Open_tables              | 1      |
    | Open_files               | 2      |
    | Open_streams             | 0      |
    | Opened_tables            | 11     |
    | Questions                | 14     |
    | Running_threads          | 1      |
    | Slow_queries             | 0      |
    | Uptime                   | 149111 |
    +--------------------------+--------+
    
    


    각각의 항목은 다음과 같은 정보를 나타낸다.

     

    Aborted_clients 클라이언트가 정상적인 종료를 하지 못하고 끊어진 접속 수
    Aborted_connects MySQL 서버네 접속을 시도했지만 실패한 접속 수
    Created_tmp_tables SQL 문을 실행하는 동안 생성된 임시 테이블 수
    Delayed_insert_threads 사용중인 지연INSER 문(delayed insert handler) 수
    Delayed_writes INSERT DELAYED에 의해 쓰여진 행수.
    Delayed_errors INSERT DELAYED에 의해 오류가 발생한 행수
    Flush_commands FLUSH 명령 실행 횟수
    Handler_delete 테이블내행 삭제명령 수
    Handler_read_first 테이블 우선 읽기 명령의 수
    Handler_read_key 인덱스 기반 테이블 읽기 명령 수
    Handler_read_next 인덱스 정렬 순서에 따라 실행된 다음 행 읽기 명령 수
    Handler_read_rnd 고정폭 테이블에서 실행된 행 읽기 명령 수
    Handler_update 테이블 UPDATE 명령 실행 수
    Handler_write 테이블 INSERT 명령 실행 수
    Key_blocks_used 인덱스 캐시에 의해 사용된 블록 수
    Key_read_requests 인덱스 캐시에 의해 처리된 명령 수
    Key_reads 디스크의 물리적 읽기 횟수
    Key_write_requests 블록이 인덱스 캐시에 저장된 명령 수
    Key_writes 블록이 물리적 디스크에 저장된 명령 수
    Max_used_connections 처리 가능한 최대 동시 접속 수
    Not_flushed_key_blocks 인덱스 캐시에 내용이 변경되었지만 아직 디스크에 저장되지 않은 블록 수
    Not_flushed_delayed_rows INSERT DELAY 에 의해 처리 지연 중인 행 수
    Open_tables 현재 사용을 위해 열려진 테이블 수
    Open_files 열려진 파일 수
    Open_streams 로그인을 위해 연결된 접속 수
    Opened_tables 지금까지 열려진 테이블 수
    Questions 서버에 의해 요청된 질문 수
    Running_threads 현재 연결중인 접속(쓰레드) 수
    Slow_queries long_query_time 에 정의 된 시간 보다 실행시간이 초과된 요청 수
    Uptime 서버 기동 후 경과 시간



    SHOW VARIABLES

    MySQL 의 시스템 변수를 출력한다. 시스템 프롬프트 상태에서 mysqladmin variables 명령을 통해서도 마찬가지 내용을 볼 수 있다. 일부 변수의 디폴트 값을 변경하려면 mysqld 를 명령행 옵션을 주어서 실행 하면 된다.

    실행결과는 다음과 비슷할 것이다.

     

    +------------------------+--------------------------+
    | Variable_name          | Value                    |
    +------------------------+--------------------------+
    | back_log               | 5                        |
    | connect_timeout        | 5                        |
    | basedir                | /my/monty/               |
    | datadir                | /my/monty/data/          |
    | delayed_insert_limit   | 100                      |
    | delayed_insert_timeout | 300                      |
    | delayed_queue_size     | 1000                     |
    | join_buffer_size       | 131072                   |
    | flush_time             | 0                        |
    | key_buffer_size        | 1048540                  |
    | language               | /my/monty/share/english/ |
    | log                    | OFF                      |
    | log_update             | OFF                      |
    | long_query_time        | 10                       |
    | low_priority_updates   | OFF                      |
    | max_allowed_packet     | 1048576                  |
    | max_connections        | 100                      |
    | max_connect_errors     | 10                       |
    | max_delayed_threads    | 20                       |
    | max_heap_table_size    | 16777216                 |
    | max_join_size          | 4294967295               |
    | max_sort_length        | 1024                     |
    | max_tmp_tables         | 32                       |
    | net_buffer_length      | 16384                    |
    | port                   | 3306                     |
    | protocol-version       | 10                       |
    | record_buffer          | 131072                   |
    | skip_locking           | ON                       |
    | socket                 | /tmp/mysql.sock          |
    | sort_buffer            | 2097116                  |
    | table_cache            | 64                       |
    | thread_stack           | 131072                   |
    | tmp_table_size         | 1048576                  |
    | tmpdir                 | /machine/tmp/            |
    | version                | 3.23.0-alpha-debug       |
    | wait_timeout           | 28800                    |
    +------------------------+--------------------------+
    



    다음 장 MySQL관리와 튜닝에서 각각의 변수에 대한 설명과 튜닝방법을 다룬다.

    SHOW PROCESSLIST
    현재 접속중인 쓰레드를 보여준다.
    shell>mysqladmin processlist 명령을 이용해도 같은 정보를 얻을 수 있다. 기본적으로 자신의 쓰레드 정보만을 볼 수 있고 PROCESS 권한을 가지고 있을 경우 모든 쓰레드 정보를 보여준다. 이 경우 KILL 명령을 이용 쓰레드를 죽일 수 있다.

    ▶ LOCK TABLES/UNLOCK TABLES

    문법 : LOCK TABLES tbl_name [AS alias] READ | [LOW_PRIORITY] WRITE [, tbl_name READ | [LOW_PRIORITY] WRITE ...] ... UNLOCK TABLES LOCK TABLES 명령은 현재 쓰레드 위해 테이블에 락(lock)을 건다. 쓰레드란 데이터베이스에 연결되는 접속 단위로 생각하면 된다. UNLOCK TABLES은 현재 쓰레드에 의해 걸린 모든 락을 푼다. 하나의 쓰레드에 의해 락이 걸린 모든 테이블은 이 쓰레드가 다른 테이블에 락을 걸 경우나 접속이 끊어질 경우 자동으로 락이 풀린다.

    만일 한 쓰레드가 어떤 테이블에 읽기(READ ) 락을 걸면 그 쓰레드의 사용자만이 그 테이블을 읽을 수 있다.

    또한 한 쓰레드가 쓰기(WRITE) 락을 걸 경우 해당 쓰레드의 사용자만이 테이블을 읽고 쓸 수 있게 된다. 다른 쓰레드들은 그 테이블에 걸린 락이 풀릴 때가지 대기하게 된다.

    일반적으로 쓰기 락이 읽기 락보다 운선 순위가 높은데 이는 가능하면 업데이트가 빨리 진행 되도록 하기 위해서이다. 다시 말해 한 쓰레드가 테이블에 읽기 락을 건 상태에서 다른 쓰레드가 테이블에 쓰기 락을 걸면 이전에 읽기 락을 건 쓰레드는 쓰기 락이 해제 될 때가지 기다리게 된다.

    일반적으로 하나의 테이블 만을 업데이트 할 경우에는 락을 걸 필요가 없다. 왜냐하면 하나의 쓰레드에서 SQL 문이 실행 중일 경우 다른 쓰레드는 이 쓰레드를 방해할 수 없기 때문이다. 드러나 때때로 락이 필요한 경우도 있다.

    만일 수많은 테이블에서 일련의 연속된 작업을 해야 하는 경우 사용하려는 테이블에 락을 경우 더 빨라질 수 있다. MySQL 은 트랜잭션(transaction) 기능을 제공하지 않으므로 만일 SELECT 와 UPDATE 사이에 다른 쓰레드가 끼어 들지 못하도록 하려면LOCK TABLES 명령을 사용해야만 한다.

    이러한 일련을 작업을 안전하게 처리하는 예가 아래에 있다.

    mysql> LOCK TABLES trans READ, customer WRITE;
    mysql> select sum(value) from trans where customer_id= some_id;
    mysql> update customer set total_value=sum_from_previous_statement
    where customer_id=some_id;
    mysql> UNLOCK TABLES;이 경우 만일 LOCK TABLES 명령을 사용하지 않은 경우 SELECT 와 UPDATE 명령 사이에 다른 사용자의 쓰레드가 끼어들 수 있다.

    ▶ GRANT / REVOKE

    문법 :

    GRANT priv_type [(column_list)] [, priv_type [(column_list)] ...]
        ON tbl_name | * | *.* | db_name.*
        TO user_name [IDENTIFIED BY 'password']
            [, user_name [IDENTIFIED BY 'password'] ...]
        [WITH GRANT OPTION]
    
    REVOKE priv_type [(column_list)] [, priv_type [(column_list)] ...]
        ON tbl_name | * | *.* | db_name.*
        FROM user_name [, user_name ...]
    

    GRANT 와 REVOKE 명령은 시스템 관리자가 데이터베이스 사용자에게 다음과 같은 4단계의 권한을 부여하거나 취소할 수 있도록 한다.

    commands allow system administrators to grant and revoke rights to MySQL users at four privilege levels:
    Global 레벨
    이 권한은 서버에 있는 모든 데이터베이스에 대한 권한으로 mysql 데이터베이스의 user 테이블에 저장된다.

    Database 레벨
    특정 데이터베이스에 존재하는 모든 테이블에 대한 권한으로 mysql 데이터베이스의 db,host 테이블에 저장된다.

    Table level
    특정 테이블에 있는 모든 컬럼에 대한 권한으로 mysql 데이터베이스의 tables_priv 테이블에 저장된다.

    Column level
    특정 테이블에 있는 하나의 컬럼에 대한 권한으로 mysql 데이터베이스의 columns _priv 테이블에 저장된다.

    한 유저가 자신의 권한을 다른 유저에게 부여하는(GRANT) 권한을 빼앗기 위해서는 다음과 같이 한다.

    REVOKE GRANT OPTION ON priv FROM user ;

    테이블에 대해 사용가능한 권한은 SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, GRANT, INDEX , ALTER. 등이 있다.

    ▶ CREATE INDEX

    인덱스를 생성한다.
    문법 : CREATE [UNIQUE] INDEX index_name ON tbl_name (col_name[(length]),... )

    CREATE INDEX 구문은 MySQL 3.22. 이전버전에서는 아무런 동작도 하지 않는다. 3.22 이후 버전에서는 CREATE INDEX 는 인덱스를 생성하는ALTER TABLE 구문과 같은 역할을 한다.

    일반적으로 모든 인덱스는 CREATE TABLE 구문을 이용해 테이블 생성시에 만들 수 있지만 CREATE INDEX 구문을 이용하면 이미 존재하는 테이블에 인덱스를 추가할 수 있다. 컬럼의 목록을 괄호 안에 (col1,col2,...) 과 같이 열거함으로써 다중 컬럼 인덱스를 만들 수 있다. 이때 생성되는 인덱스 값은 두 컬럼의 조합으로 만들어 진다.

    컬럼의 일부만 인덱스로 생성 CHAR 와 VARCHAR 컬럼에서는 col_name(length) 처럼 length를 지정해 줌으로써 컬럼의 일부분만을 사용할 수 있다.

    아래의 예를 name 컬럼의 앞부분 10 자리만을 인덱스로 만드는 것을 보여준다.
    mysql> CREATE INDEX part_of_name ON customer (name(10));
    이 경우 이름 전체를 인덱스로 만드는 것보다 검색속도는 느려지겠지만 많은 디스크 공간을 절약할 수 있고 INSERT 수행 시 속도가 향상된다.

    ▶ DROP INDEX

    문법 : DROP INDEX index_name

    인덱스를 삭제한다. DROP INDEX 구문은 MySQL 3.22. 이전버전에서는 아무런 동작도 하지 않는다. 3.22 이후 버전에서는 DROP INDEX 는 인덱스를 삭제하는ALTER TABLE 구문과 같은 역할을 한다.