캠핑과 개발

원문 : http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

번역 : 구글번역



소개(Intorduction)


한 번에 또는 대부분의 사용자는 SQL 데이터베이스에서 계층 적 데이터를 처리했으며 계층 적 데이터의 관리는 관계형 데이터베이스의 의도와 다르다는 것을 알게되었습니다. 관계형 데이터베이스의 테이블은 XML과 같은 계층 적 구조는 아니지만 단순한 플랫 목록입니다. 계층 적 데이터는 관계형 데이터베이스 테이블에서 자연스럽게 표현되지 않는 부모 - 자식 관계를가집니다.


우리의 목적을 위해 계층 적 데이터는 각 항목이 하나의 부모와 0 개 이상의 자식을 가진 데이터 모음입니다 (상위 항목이없는 루트 항목 제외). 계층 적 데이터는 포럼 및 메일 목록 스레드, 비즈니스 조직도, 콘텐츠 관리 범주 및 제품 범주를 비롯한 다양한 데이터베이스 응용 프로그램에서 찾을 수 있습니다. 우리의 목적을 위해 가상의 전자 제품 상점에서 다음과 같은 제품 카테고리 계층 구조를 사용합니다.




이 범주는 위에 인용 된 다른 예제와 동일한 방식으로 계층 구조를 형성합니다. 이 기사에서는 전통적인 adjacency list 모델부터 시작하여 MySQL의 계층 적 데이터를 다루는 두 가지 모델을 살펴 보겠습니다.




인접 목록 모델(The Adjacency List Model)


일반적으로 위에 표시된 예제 카테고리는 다음과 같은 테이블에 저장됩니다 (전체 CREATE 및 INSERT 문을 포함하므로 따라갈 수 있습니다).


CREATE TABLE category(
        category_id INT AUTO_INCREMENT PRIMARY KEY,
        name VARCHAR(20) NOT NULL,
        parent INT DEFAULT NULL
);

INSERT INTO category VALUES(1,'ELECTRONICS',NULL),(2,'TELEVISIONS',1),(3,'TUBE',2),
        (4,'LCD',2),(5,'PLASMA',2),(6,'PORTABLE ELECTRONICS',1),(7,'MP3 PLAYERS',6),(8,'FLASH',7),
        (9,'CD PLAYERS',6),(10,'2 WAY RADIOS',6);

SELECT * FROM category ORDER BY category_id;
+-------------+----------------------+--------+
| category_id | name                 | parent |
+-------------+----------------------+--------+
|           1 | ELECTRONICS          |   NULL |
|           2 | TELEVISIONS          |      1 |
|           3 | TUBE                 |      2 |
|           4 | LCD                  |      2 |
|           5 | PLASMA               |      2 |
|           6 | PORTABLE ELECTRONICS |      1 |
|           7 | MP3 PLAYERS          |      6 |
|           8 | FLASH                |      7 |
|           9 | CD PLAYERS           |      6 |
|          10 | 2 WAY RADIOS         |      6 |
+-------------+----------------------+--------+
10 rows in set (0.00 sec)

인접성 목록 모델에서 테이블의 각 항목에는 상위 항목에 대한 포인터가 포함됩니다. 최상위 요소 (이 경우 electronics)는 상위 요소에 대해 NULL 값을가집니다. 인접 목록 모델은 아주 간단하다는 장점이 있으며, FLASH가 mp3 플레이어의 하위 항목 인 전자 제품의 하위 항목 인 휴대용 전자 제품의 하위 항목임을 쉽게 알 수 있습니다. 인접 목록 모델은 클라이언트 측 코드에서 상당히 쉽게 처리 할 수 있지만 모델로 작업하는 것은 순수 SQL에서 더 문제가 될 수 있습니다.



풀 트리 검색하기(RETRIEVING A FULL TREE)


계층 적 데이터를 처리 할 때 첫 번째로 공통적으로 수행해야 할 작업은 일반적으로 들여 쓰기의 형태로 전체 트리를 표시하는 것입니다. 이 작업을 수행하는 가장 일반적인 방법은 순수한 SQL에서 자체 조인을 사용하는 것입니다.


SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4
FROM category AS t1
LEFT JOIN category AS t2 ON t2.parent = t1.category_id
LEFT JOIN category AS t3 ON t3.parent = t2.category_id
LEFT JOIN category AS t4 ON t4.parent = t3.category_id
WHERE t1.name = 'ELECTRONICS';

+-------------+----------------------+--------------+-------+
| lev1        | lev2                 | lev3         | lev4  |
+-------------+----------------------+--------------+-------+
| ELECTRONICS | TELEVISIONS          | TUBE         | NULL  |
| ELECTRONICS | TELEVISIONS          | LCD          | NULL  |
| ELECTRONICS | TELEVISIONS          | PLASMA       | NULL  |
| ELECTRONICS | PORTABLE ELECTRONICS | MP3 PLAYERS  | FLASH |
| ELECTRONICS | PORTABLE ELECTRONICS | CD PLAYERS   | NULL  |
| ELECTRONICS | PORTABLE ELECTRONICS | 2 WAY RADIOS | NULL  |
+-------------+----------------------+--------------+-------+
6 rows in set (0.00 sec)


모든 잎사귀 찾기(FINDING ALL THE LEAF NODES)


LEFT JOIN 쿼리를 사용하여 트리에있는 모든 리프 노드 (자식이없는 노드)를 찾을 수 있습니다.


SELECT t1.name FROM
category AS t1 LEFT JOIN category as t2
ON t1.category_id = t2.parent
WHERE t2.category_id IS NULL;

+--------------+
| name         |
+--------------+
| TUBE         |
| LCD          |
| PLASMA       |
| FLASH        |
| CD PLAYERS   |
| 2 WAY RADIOS |
+--------------+



단일 경로 검색(RETRIEVING A SINGLE PATH)


자체 조인은 또한 우리가 계층 구조를 통해 완전한 경로를 볼 수있게 해줍니다 :


SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4
FROM category AS t1
LEFT JOIN category AS t2 ON t2.parent = t1.category_id
LEFT JOIN category AS t3 ON t3.parent = t2.category_id
LEFT JOIN category AS t4 ON t4.parent = t3.category_id
WHERE t1.name = 'ELECTRONICS' AND t4.name = 'FLASH';

+-------------+----------------------+-------------+-------+
| lev1        | lev2                 | lev3        | lev4  |
+-------------+----------------------+-------------+-------+
| ELECTRONICS | PORTABLE ELECTRONICS | MP3 PLAYERS | FLASH |
+-------------+----------------------+-------------+-------+
1 row in set (0.01 sec)

이러한 접근 방식의 주된 한계는 계층 구조의 모든 수준에 대해 하나의 자체 조인이 필요하며 조인이 복잡해지면서 각 수준이 추가 될 때마다 성능이 자연스럽게 저하된다는 것입니다.



부작용 목록 모델의 제한(LIMITATIONS OF THE ADJACENCY LIST MODEL)


순수 SQL에서 인접성 목록 모델로 작업하는 것은 기껏해야 어려울 수 있습니다. 카테고리의 전체 경로를 표시되기 전에, 우리는 존재하는 레벨을 알 수있다. 그 과정에서 전체 서브 트리를 orphaning에 대한 때문에 가능성의 노드를 삭제하는 경우 또한, 특별한주의는 (휴대용 전자 제품 카테고리와 분리되어 자식을 모두 삭제)주의해야합니다. 이러한 제한 중 일부는 클라이언트 측 코드 나 저장 프로 시저를 사용하여 해결할 수 있습니다. 절차 언어로 우리는 나무의 아래에서 시작하여 전체 트리 또는 단일 경로를 반환 위쪽으로 반복 할 수 있습니다. 프로 시저 프로그래밍을 사용하여 하나의 자식 요소를 승격시키고 나머지 자식을 새로운 부모를 가리 키도록 다시 정렬함으로써 전체 하위 트리를 고아없이 노드를 삭제할 수도 있습니다.



중첩 세트 모델(The Nested Set Model)


이 기사에서 중점을두고 자하는 것은 일반적으로 중첩 세트 모델이라고하는 다른 접근 방식입니다. 중첩 세트 모델에서는 노드와 라인이 아닌 중첩 된 컨테이너로 새로운 방식으로 계층 구조를 볼 수 있습니다. 다음과 같이 전자 제품 범주를 묘사 해보십시오.



부모 범주가 자녀를 감싸고 있기 때문에 우리 계층 구조가 어떻게 유지되고 있는지 주목하십시오. 우리는 노드의 중첩을 나타 내기 위해 왼쪽 및 오른쪽 값을 사용하여 테이블에서이 계층 구조를 나타냅니다.


CREATE TABLE nested_category (
        category_id INT AUTO_INCREMENT PRIMARY KEY,
        name VARCHAR(20) NOT NULL,
        lft INT NOT NULL,
        rgt INT NOT NULL
);

INSERT INTO nested_category VALUES(1,'ELECTRONICS',1,20),(2,'TELEVISIONS',2,9),(3,'TUBE',3,4),
 (4,'LCD',5,6),(5,'PLASMA',7,8),(6,'PORTABLE ELECTRONICS',10,19),(7,'MP3 PLAYERS',11,14),(8,'FLASH',12,13),
 (9,'CD PLAYERS',15,16),(10,'2 WAY RADIOS',17,18);

SELECT * FROM nested_category ORDER BY category_id;

+-------------+----------------------+-----+-----+
| category_id | name                 | lft | rgt |
+-------------+----------------------+-----+-----+
|           1 | ELECTRONICS          |   1 |  20 |
|           2 | TELEVISIONS          |   2 |   9 |
|           3 | TUBE                 |   3 |   4 |
|           4 | LCD                  |   5 |   6 |
|           5 | PLASMA               |   7 |   8 |
|           6 | PORTABLE ELECTRONICS |  10 |  19 |
|           7 | MP3 PLAYERS          |  11 |  14 |
|           8 | FLASH                |  12 |  13 |
|           9 | CD PLAYERS           |  15 |  16 |
|          10 | 2 WAY RADIOS         |  17 |  18 |
+-------------+----------------------+-----+-----+

왼쪽과 오른쪽은 MySQL에서 예약어이기 때문에 lft와 rgt를 사용합니다. 예약어 전체 목록은 http://dev.mysql.com/doc/mysql/en/reserved-words.html을 참조하십시오.


그렇다면 우리는 어떻게 좌우 값을 결정합니까? 바깥 쪽 노드의 가장 왼쪽에 번호를 매기고 오른쪽으로 계속합니다.





이 디자인은 일반적인 트리에도 적용 할 수 있습니다.



트리를 사용하여 작업 할 때 우리는 왼쪽에서 오른쪽으로 한 번에 한 레이어 씩 작업하고 각 노드의 하위 노드로 내림차순 번호를 할당하고 오른쪽으로 이동합니다. 이 접근법을 수정 된 선주문 트리 순회 알고리즘이라고합니다.




풀 트리 검색하기(RETRIEVING A FULL TREE)


우리는 노드의 lft 값이 부모의 lft와 rgt 값 사이에 항상 존재한다는 것을 기반으로 부모를 노드와 연결하는 자체 조인을 사용하여 전체 트리를 검색 할 수 있습니다.


SELECT node.name
FROM nested_category AS node,
        nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
        AND parent.name = 'ELECTRONICS'
ORDER BY node.lft;

+----------------------+
| name                 |
+----------------------+
| ELECTRONICS          |
| TELEVISIONS          |
| TUBE                 |
| LCD                  |
| PLASMA               |
| PORTABLE ELECTRONICS |
| MP3 PLAYERS          |
| FLASH                |
| CD PLAYERS           |
| 2 WAY RADIOS         |
+----------------------+


인접성 목록 모델을 사용한 이전 예제와 달리이 쿼리는 트리의 깊이에 관계없이 작동합니다. rgt 값은 항상 lft 값과 같은 부모 내에 속하기 때문에 우리는 BETWEEN 절의 노드의 rgt 값에 신경 쓰지 않습니다.




모든 잎사귀 찾기(FINDING ALL THE LEAF NODES)


인접 목록 모델에서 사용 된 LEFT JOIN 방법보다 훨씬 단순한 중첩 된 집합 모델의 모든 리프 노드 찾기. nested_category 테이블을 보면 리프 노드의 lft 및 rgt 값이 연속 된 숫자임을 알 수 있습니다. 리프 노드를 찾기 위해 rgt = lft + 1 인 노드를 찾는다.


SELECT name
FROM nested_category
WHERE rgt = lft + 1;

+--------------+
| name         |
+--------------+
| TUBE         |
| LCD          |
| PLASMA       |
| FLASH        |
| CD PLAYERS   |
| 2 WAY RADIOS |
+--------------+



단일 경로 검색(RETRIEVING A SINGLE PATH)


중첩 된 집합 모델을 사용하면 여러자가 조인을 사용하지 않고도 단일 경로를 검색 할 수 있습니다.


SELECT parent.name
FROM nested_category AS node,
        nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
        AND node.name = 'FLASH'
ORDER BY parent.lft;

+----------------------+
| name                 |
+----------------------+
| ELECTRONICS          |
| PORTABLE ELECTRONICS |
| MP3 PLAYERS          |
| FLASH                |
+----------------------+


NODES의 깊이 찾기(FINDING THE DEPTH OF THE NODES)


우리는 이미 전체 트리를 표시하는 방법을 살펴 보았지만 트리의 각 노드의 깊이를 표시하여 각 노드가 계층 구조에 어떻게 들어 맞는지 더 잘 식별하려는 경우 어떻게해야할까요? 이것은 전체 트리를 표시하기 위해 COUNT 함수와 GROUP BY 절을 기존 쿼리에 추가하여 수행 할 수 있습니다.


SELECT node.name, (COUNT(parent.name) - 1) AS depth
FROM nested_category AS node,
        nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
GROUP BY node.name
ORDER BY node.lft;

+----------------------+-------+
| name                 | depth |
+----------------------+-------+
| ELECTRONICS          |     0 |
| TELEVISIONS          |     1 |
| TUBE                 |     2 |
| LCD                  |     2 |
| PLASMA               |     2 |
| PORTABLE ELECTRONICS |     1 |
| MP3 PLAYERS          |     2 |
| FLASH                |     3 |
| CD PLAYERS           |     2 |
| 2 WAY RADIOS         |     2 |
+----------------------+-------+

depth 값을 사용하여 범주 이름을 CONCAT 및 REPEAT 문자열 함수로 들여 쓸 수 있습니다.


SELECT CONCAT( REPEAT(' ', COUNT(parent.name) - 1), node.name) AS name
FROM nested_category AS node,
        nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
GROUP BY node.name
ORDER BY node.lft;

+-----------------------+
| name                  |
+-----------------------+
| ELECTRONICS           |
|  TELEVISIONS          |
|   TUBE                |
|   LCD                 |
|   PLASMA              |
|  PORTABLE ELECTRONICS |
|   MP3 PLAYERS         |
|    FLASH              |
|   CD PLAYERS          |
|   2 WAY RADIOS        |
+-----------------------+

물론 클라이언트 측 응용 프로그램에서는 깊이 값을 직접 사용하여 계층 구조를 표시 할 가능성이 높습니다. 웹 개발자는 깊이 번호가 증가하거나 감소 할 때 <li> </ li> 및 <ul> </ ul> 태그를 추가하여 트리를 반복 할 수 있습니다.



서브 트리의 깊이(DEPTH OF A SUB-TREE)


하위 트리에 대한 깊이 정보가 필요하면 결과를 손상시킬 수 있으므로 자체 조인에서 노드 또는 부모 테이블을 제한 할 수 없습니다. 대신 세 번째 자체 조인을 하위 쿼리와 함께 추가하여 하위 트리의 새로운 시작점이 될 깊이를 결정합니다.


SELECT node.name, (COUNT(parent.name) - (sub_tree.depth + 1)) AS depth
FROM nested_category AS node,
        nested_category AS parent,
        nested_category AS sub_parent,
        (
                SELECT node.name, (COUNT(parent.name) - 1) AS depth
                FROM nested_category AS node,
                nested_category AS parent
                WHERE node.lft BETWEEN parent.lft AND parent.rgt
                AND node.name = 'PORTABLE ELECTRONICS'
                GROUP BY node.name
                ORDER BY node.lft
        )AS sub_tree
WHERE node.lft BETWEEN parent.lft AND parent.rgt
        AND node.lft BETWEEN sub_parent.lft AND sub_parent.rgt
        AND sub_parent.name = sub_tree.name
GROUP BY node.name
ORDER BY node.lft;

+----------------------+-------+
| name                 | depth |
+----------------------+-------+
| PORTABLE ELECTRONICS |     0 |
| MP3 PLAYERS          |     1 |
| FLASH                |     2 |
| CD PLAYERS           |     1 |
| 2 WAY RADIOS         |     1 |
+----------------------+-------+

이 기능은 루트 노드를 포함한 모든 노드 이름과 함께 사용할 수 있습니다. 깊이 값은 항상 명명 된 노드를 기준으로합니다.



NODE의 즉각적인 소굴 찾기(FIND THE IMMEDIATE SUBORDINATES OF A NODE)


소매업 자 웹 사이트에서 전자 제품 범주를 보여주고 있다고 가정 해보십시오. 사용자가 카테고리를 클릭하면 해당 카테고리의 제품을 표시하고 그 바로 아래의 하위 카테고리는 나열하지만 하위 카테고리의 전체 트리는 나열하지 않을 수 있습니다. 이를 위해 우리는 노드와 노드의 즉각적인 하위 노드를 보여줄 필요가 있지만 트리를 더 내려 가지 않아야합니다. 예를 들어 휴대용 전자 제품 카테고리를 표시 할 때 MP3 플레이어, CD 플레이어 및 2 가지 라디오를 표시하려고하지만 플래시는 표시하지 않을 것입니다.


이는 이전 쿼리에 HAVING 절을 추가하여 쉽게 수행 할 수 있습니다.


SELECT node.name, (COUNT(parent.name) - (sub_tree.depth + 1)) AS depth
FROM nested_category AS node,
        nested_category AS parent,
        nested_category AS sub_parent,
        (
                SELECT node.name, (COUNT(parent.name) - 1) AS depth
                FROM nested_category AS node,
                        nested_category AS parent
                WHERE node.lft BETWEEN parent.lft AND parent.rgt
                        AND node.name = 'PORTABLE ELECTRONICS'
                GROUP BY node.name
                ORDER BY node.lft
        )AS sub_tree
WHERE node.lft BETWEEN parent.lft AND parent.rgt
        AND node.lft BETWEEN sub_parent.lft AND sub_parent.rgt
        AND sub_parent.name = sub_tree.name
GROUP BY node.name
HAVING depth <= 1
ORDER BY node.lft;

+----------------------+-------+
| name                 | depth |
+----------------------+-------+
| PORTABLE ELECTRONICS |     0 |
| MP3 PLAYERS          |     1 |
| CD PLAYERS           |     1 |
| 2 WAY RADIOS         |     1 |
+----------------------+-------+


상위 노드를 표시하지 않으려면, HAVING depth <= 1 행을 HAVING depth = 1로 변경하십시오.



중첩 된 기능의 전체 기능(AGGREGATE FUNCTIONS IN A NESTED SET)


집계 함수를 설명하는 데 사용할 수있는 제품 표를 추가해 보겠습니다.


CREATE TABLE product
(
        product_id INT AUTO_INCREMENT PRIMARY KEY,
        name VARCHAR(40),
        category_id INT NOT NULL
);

INSERT INTO product(name, category_id) VALUES('20" TV',3),('36" TV',3),
('Super-LCD 42"',4),('Ultra-Plasma 62"',5),('Value Plasma 38"',5),
('Power-MP3 5gb',7),('Super-Player 1gb',8),('Porta CD',9),('CD To go!',9),
('Family Talk 360',10);

SELECT * FROM product;

+------------+-------------------+-------------+
| product_id | name              | category_id |
+------------+-------------------+-------------+
|          1 | 20" TV            |           3 |
|          2 | 36" TV            |           3 |
|          3 | Super-LCD 42"     |           4 |
|          4 | Ultra-Plasma 62"  |           5 |
|          5 | Value Plasma 38"  |           5 |
|          6 | Power-MP3 128mb   |           7 |
|          7 | Super-Shuffle 1gb |           8 |
|          8 | Porta CD          |           9 |
|          9 | CD To go!         |           9 |
|         10 | Family Talk 360   |          10 |
+------------+-------------------+-------------+



이제 각 카테고리의 제품 수와 함께 카테고리 트리를 검색 할 수있는 쿼리를 생성 해 보겠습니다.


SELECT parent.name, COUNT(product.name)
FROM nested_category AS node ,
        nested_category AS parent,
        product
WHERE node.lft BETWEEN parent.lft AND parent.rgt
        AND node.category_id = product.category_id
GROUP BY parent.name
ORDER BY node.lft;

+----------------------+---------------------+
| name                 | COUNT(product.name) |
+----------------------+---------------------+
| ELECTRONICS          |                  10 |
| TELEVISIONS          |                   5 |
| TUBE                 |                   2 |
| LCD                  |                   1 |
| PLASMA               |                   2 |
| PORTABLE ELECTRONICS |                   5 |
| MP3 PLAYERS          |                   2 |
| FLASH                |                   1 |
| CD PLAYERS           |                   2 |
| 2 WAY RADIOS         |                   1 |
+----------------------+---------------------+


이것은 COUNT 및 GROUP BY가 추가 된 일반적인 트리 전체 쿼리와 WHERE 절의 노드와 product 테이블 간의 조인 및 product 테이블에 대한 참조입니다. 보시다시피 각 카테고리에 대한 개수가 있으며 하위 카테고리의 수는 상위 카테고리에 반영됩니다.



새로운 노드 추가하기(ADDING NEW NODES)


이제 트리를 쿼리하는 방법을 배웠으므로 새 노드를 추가하여 트리를 업데이트하는 방법을 살펴보아야합니다. 중첩 된 집합 다이어그램을 다시 살펴 보겠습니다.




TELEVISIONS 노드와 PORTABLE ELECTRONICS 노드 사이에 새로운 노드를 추가하고자한다면, 새로운 노드는 lft와 rgt 값이 10과 11이 될 것이고, 오른쪽 노드는 lft와 rgt 값이 2만큼 증가 할 것입니다. 그런 다음 적절한 lft 및 rgt 값을 가진 새 노드를 추가합니다. 이 작업은 MySQL 5의 저장 프로 시저에서 수행 할 수 있지만 가장 안정적인 버전이므로 대부분의 독자가 4.1을 사용하고 있다고 가정하고 대신 LOCK TABLES 문으로 쿼리를 분리합니다.


LOCK TABLE nested_category WRITE;

SELECT @myRight := rgt FROM nested_category
WHERE name = 'TELEVISIONS';

UPDATE nested_category SET rgt = rgt + 2 WHERE rgt > @myRight;
UPDATE nested_category SET lft = lft + 2 WHERE lft > @myRight;

INSERT INTO nested_category(name, lft, rgt) VALUES('GAME CONSOLES', @myRight + 1, @myRight + 2);

UNLOCK TABLES;

우리는 들여 쓰기 트리 쿼리를 사용하여 중첩을 확인할 수 있습니다.


SELECT CONCAT( REPEAT( ' ', (COUNT(parent.name) - 1) ), node.name) AS name
FROM nested_category AS node,
        nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
GROUP BY node.name
ORDER BY node.lft;

+-----------------------+
| name                  |
+-----------------------+
| ELECTRONICS           |
|  TELEVISIONS          |
|   TUBE                |
|   LCD                 |
|   PLASMA              |
|  GAME CONSOLES        |
|  PORTABLE ELECTRONICS |
|   MP3 PLAYERS         |
|    FLASH              |
|   CD PLAYERS          |
|   2 WAY RADIOS        |
+-----------------------+



기존의 자식이없는 노드의 자식으로 노드를 추가하려면이 절차를 약간 수정해야합니다. 2 WAY RADIOS 노드 아래에 새 FRS 노드를 추가해 보겠습니다.


LOCK TABLE nested_category WRITE;

SELECT @myLeft := lft FROM nested_category

WHERE name = '2 WAY RADIOS';

UPDATE nested_category SET rgt = rgt + 2 WHERE rgt > @myLeft;
UPDATE nested_category SET lft = lft + 2 WHERE lft > @myLeft;

INSERT INTO nested_category(name, lft, rgt) VALUES('FRS', @myLeft + 1, @myLeft + 2);

UNLOCK TABLES;

이 예제에서 우리는 자랑스러운 새로운 부모 노드의 왼쪽 숫자의 오른쪽으로 모든 것을 확장 한 다음 노드를 왼쪽 값의 오른쪽에 배치합니다. 보시다시피 새 노드가 제대로 중첩되었습니다.


SELECT CONCAT( REPEAT( ' ', (COUNT(parent.name) - 1) ), node.name) AS name
FROM nested_category AS node,
        nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
GROUP BY node.name
ORDER BY node.lft;

+-----------------------+
| name                  |
+-----------------------+
| ELECTRONICS           |
|  TELEVISIONS          |
|   TUBE                |
|   LCD                 |
|   PLASMA              |
|  GAME CONSOLES        |
|  PORTABLE ELECTRONICS |
|   MP3 PLAYERS         |
|    FLASH              |
|   CD PLAYERS          |
|   2 WAY RADIOS        |
|    FRS                |
+-----------------------+


노드 삭제(DELETING NODES)


중첩 된 세트를 사용하여 작업하는 마지막 기본 작업은 노드를 제거하는 것입니다. 노드를 삭제할 때 수행하는 과정은 계층 구조에서 노드의 위치에 따라 달라집니다. 분리 된 노드를 처리해야하기 때문에 리프 노드를 삭제하는 것이 자식 노드를 삭제하는 것보다 쉽습니다.


잎 노드를 삭제할 때, 새로운 노드를 추가하는 것과 정반대의 과정을 거치면 모든 노드에서 오른쪽으로 노드와 노드의 너비가 삭제됩니다.


LOCK TABLE nested_category WRITE;

SELECT @myLeft := lft, @myRight := rgt, @myWidth := rgt - lft + 1
FROM nested_category
WHERE name = 'GAME CONSOLES';

DELETE FROM nested_category WHERE lft BETWEEN @myLeft AND @myRight;

UPDATE nested_category SET rgt = rgt - @myWidth WHERE rgt > @myRight;
UPDATE nested_category SET lft = lft - @myWidth WHERE lft > @myRight;

UNLOCK TABLES;

그리고 다시 한번 들여 쓰기 트리 쿼리를 실행하여 노드가 계층 구조를 손상시키지 않고 삭제되었음을 확인합니다.


SELECT CONCAT( REPEAT( ' ', (COUNT(parent.name) - 1) ), node.name) AS name
FROM nested_category AS node,
        nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
GROUP BY node.name
ORDER BY node.lft;

+-----------------------+
| name                  |
+-----------------------+
| ELECTRONICS           |
|  TELEVISIONS          |
|   TUBE                |
|   LCD                 |
|   PLASMA              |
|  PORTABLE ELECTRONICS |
|   MP3 PLAYERS         |
|    FLASH              |
|   CD PLAYERS          |
|   2 WAY RADIOS        |
|    FRS                |
+-----------------------+


이 접근법은 노드와 그 모든 자식 노드를 삭제하는 것과 똑같이 잘 작동합니다.


LOCK TABLE nested_category WRITE;

SELECT @myLeft := lft, @myRight := rgt, @myWidth := rgt - lft + 1
FROM nested_category
WHERE name = 'MP3 PLAYERS';

DELETE FROM nested_category WHERE lft BETWEEN @myLeft AND @myRight;

UPDATE nested_category SET rgt = rgt - @myWidth WHERE rgt > @myRight;
UPDATE nested_category SET lft = lft - @myWidth WHERE lft > @myRight;

UNLOCK TABLES;

다시 한번 전체 하위 트리를 성공적으로 삭제했는지 쿼리합니다.


SELECT CONCAT( REPEAT( ' ', (COUNT(parent.name) - 1) ), node.name) AS name
FROM nested_category AS node,
        nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
GROUP BY node.name
ORDER BY node.lft;

+-----------------------+
| name                  |
+-----------------------+
| ELECTRONICS           |
|  TELEVISIONS          |
|   TUBE                |
|   LCD                 |
|   PLASMA              |
|  PORTABLE ELECTRONICS |
|   CD PLAYERS          |
|   2 WAY RADIOS        |
|    FRS                |
+-----------------------+

우리가 처리해야하는 또 다른 시나리오는 부모 노드는 삭제하지만 자식 노드는 삭제하지 않는 것입니다. 어떤 경우에는 감독자가 해고 될 때와 같이 대체가 표시 될 때까지 이름을 자리 표시 자로 바꿀 수도 있습니다. 다른 경우, 자식 노드는 모두 삭제 된 부모 수준까지 이동해야합니다.


LOCK TABLE nested_category WRITE;

SELECT @myLeft := lft, @myRight := rgt, @myWidth := rgt - lft + 1
FROM nested_category
WHERE name = 'PORTABLE ELECTRONICS';

DELETE FROM nested_category WHERE lft = @myLeft;

UPDATE nested_category SET rgt = rgt - 1, lft = lft - 1 WHERE lft BETWEEN @myLeft AND @myRight;
UPDATE nested_category SET rgt = rgt - 2 WHERE rgt > @myRight;
UPDATE nested_category SET lft = lft - 2 WHERE lft > @myRight;

UNLOCK TABLES;

이 경우 노드의 오른쪽에있는 모든 요소에서 2를 뺍니다 (자식이 없으므로 너비가 2가되기 때문에). 자식 노드가 하나 인 노드에서 하나를 뺍니다 (부모의 왼쪽 손실로 인해 생성 된 간격을 닫습니다. 값). 다시 한번, 우리는 요소가 홍보되었음을 확인할 수 있습니다.


SELECT CONCAT( REPEAT( ' ', (COUNT(parent.name) - 1) ), node.name) AS name
FROM nested_category AS node,
        nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
GROUP BY node.name
ORDER BY node.lft;

+---------------+
| name          |
+---------------+
| ELECTRONICS   |
|  TELEVISIONS  |
|   TUBE        |
|   LCD         |
|   PLASMA      |
|  CD PLAYERS   |
|  2 WAY RADIOS |
|   FRS         |
+---------------+

노드를 삭제할 때의 다른 시나리오는 자식 노드 중 하나를 부모 위치로 승격시키고 부모 노드의 형제 노드 아래에 자식 노드를 이동시키는 것입니다. 그러나 공간을 위해이 시나리오는이 기사에서 다루지 않습니다.




최종 생각(Final Thoughts)


이 기사의 정보가 사용자에게 유용하기를 희망하지만 SQL에서 중첩 된 집합의 개념은 10 년 이상되어 왔으며 책과 인터넷에서 사용할 수있는 많은 추가 정보가 있습니다. 제 생각에 계층 적 정보를 관리하는 데있어 가장 포괄적 인 정보원은 고급 SQL, Joe Celko 분야에서 매우 존경받는 저자가 작성한 Joe Celko의 "Smarties 용 SQL의 Trees and Hierarchies"입니다. 조 셀코 (Joe Celko)는 중첩 된 세트 모델로 종종 공로를 인정 받았으며이 주제에 관한 가장 많은 저술가입니다. Celko의 저서가 저의 연구에서 귀중한 자원이라는 것을 알았습니다. 이 기사에서는이 기사에서 다루지 않은 고급 항목에 대해 설명하고 인접 목록 및 중첩 세트 모델 외에도 계층 적 데이터를 관리하기위한 추가 방법을 제공합니다.


참고 자료 / 참고 자료 섹션에서 나는 MySQL에서 중첩 된 세트를 처리하기 위해 미리 빌드 된 PHP 라이브러리를 포함하는 한 쌍의 PHP 관련 리소스를 포함하여 계층 적 데이터 관리 연구에 사용할 수있는 웹 리소스를 나열했다. 현재 인접 목록 모델을 사용 중이며 중첩 된 세트 모델을 실험하고 싶은 사용자는 아래에 나열된 데이터베이스 리소스의 계층 적 데이터 저장에서 둘 사이의 변환을위한 샘플 코드를 찾을 수 있습니다.







##MySQL에서 테이블 생성 스크립트를 보고 싶을때 사용

show create table [table명]

 

##MySQL에서 DB에 생성된 모든 테이블을 보고 싶을때 

show tables

like절 사용가능

show tables like '%tba_%'


[출처] [MySQL] Table Schema 보기|작성자 juner84

'DEVELOPMENT > Database' 카테고리의 다른 글

ORACLE 테이블 스페이스 관리 명령  (0) 2014.04.02
[ 오라클 ] 테이블 락 조회/ 해제 방법  (0) 2013.04.23
mysql DB 백업  (0) 2012.05.17
MySQL table 용량 확인  (0) 2012.05.17
DB link 생성  (0) 2012.05.17

# mysqldump 사용법

mysqldump [옵션] -u root -p [DB이름] > [백업파일명].sql

 

[백업파일명].sql 파일을 열어보면 각각의 데이타베이스를 create 시키는부분과 각각의 데이타베이스마다 테이블을 create 시키는부분, 그리고 테이블에 데이터를 insert 시키는 부분들이 모두 있음

 

mysqldump 옵션(출처 :http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html)

-A, --all-databases : 모든 DB를 덤프 

--add-locks : 덤프 전에 lock 덤프 후에 unlock 

--add-drop-table : 덤프이후에 출력물의 앞에 drop table명령 추가 복구할 때 사용키 위해서 

-B, --databases : 여러 DB를 동시에 덤프 할 때 사용 

-f, --force : 에러를 무시 

-h, --host : 지정한 호스트의 데이터를 덤프 

-t, --no-create-info : 데이터만 덤프 

-d, --no-data : 데이터를 제외하고 스키마만 덤프 

-p : 사용자의 암호를 지정 

-P : 포트번호 지정 

-u : 사용자명 지정

 

# DB 복구

mysql -u root -p [복구할 DB명] < [백업파일명].sql

※ 미리 DB를 만들어 두어야 함

복구시 가끔 한글이 깨지는 경우 존재 그럴땐 --default-character-set=euckr 옵션사용

mysql -u root -p --default-character-set=euckr [복구할 DB명] < [백업파일명].sql


[출처] [Mysql] mysqldump로 DB백업 받기|작성자 juner84

'DEVELOPMENT > Database' 카테고리의 다른 글

[ 오라클 ] 테이블 락 조회/ 해제 방법  (0) 2013.04.23
MySQL Table Schema 확인  (0) 2012.05.17
MySQL table 용량 확인  (0) 2012.05.17
DB link 생성  (0) 2012.05.17
index 생성  (0) 2012.05.17

DB를 사용하다 보면 table별 용량 확인이 필요할 때가 있다.

mysql에서 meta정보를 확인하기 위해서는 information_schema를 이용하면 된다.

이번 포스트에서는 table용량 확인을 위한 sql을 정리하기로 하자....



[DB 용량확인]

SELECT table_schema "Database Name", 

            SUM(data_length + index_length) / 1024 / 1024 "Size(MB)" 

FROM information_schema.TABLES 

GROUP BY table_schema;


[table 용량확인]

SELECT 

    concat(table_schema,'.',table_name),   

    concat(round(table_rows/1000000,2),'M') rows,   

    concat(round(data_length/(1024*1024*1024),2),'G') DATA,   

    concat(round(index_length/(1024*1024*1024),2),'G') idx,   

    concat(round((data_length+index_length)/(1024*1024*1024),2),'G') total_size,   

    round(index_length/data_length,2) idxfrac    

FROM information_schema.TABLES  

    where table_name = '테이블명'  ;



[출처] [MySQL] database table용량 확인|작성자 juner84

'DEVELOPMENT > Database' 카테고리의 다른 글

MySQL Table Schema 확인  (0) 2012.05.17
mysql DB 백업  (0) 2012.05.17
DB link 생성  (0) 2012.05.17
index 생성  (0) 2012.05.17
Oracle Hint  (0) 2012.05.17


## // MySQL의 default configuration 파일의 위치는 한 곳에 지정되거나
## // 어딘가에 명확히 명시되어서 실행되지 않는 것이 일반적이다.
## // 이런 경우, 현재 mysql server가 어느 위치에 있는 my.cnf 파일을 읽었는지 궁금한 경우가 많다.
## // 또한 my.cnf 파일은 RPM으로 MySQL library만 설치해도 /etc/my.cnf 파일이 생성되므로
## // mysql server가 DBA가 준비해둔 설정 파일을 읽었는지, 아니면 위처럼 의도하지 않게 
## // 생성된 my.cnf 파일을 읽고 있는지 의심이 되는 경우가 매우 허다한데, 
## // 이런 경우에는 아래와 같이 mysql server 프로세스가 기본적으로 찾게 되는 my.cnf 파일의
## // 경로를 우선순위대로 확인해볼 수 있다.

${MYSQL_HOME}/bin/mysqld --verbose --help | grep -A 1 'Default options'

Default options are read from the following fi
les in the given

'DEVELOPMENT > Database' 카테고리의 다른 글

index 생성  (0) 2012.05.17
Oracle Hint  (0) 2012.05.17
mysql 소스 설치  (0) 2011.11.29
ORACLE 명령문  (0) 2011.08.02
MERGE INTO 사용법  (0) 2011.07.09


http://dev.mysql.com 에서 다운로드 후 설치

mysql 5.1 바이너리 설치

[바이너리 버전 설치 순서]
shell> groupadd mysql
shell> useradd -g mysql mysql
shell> cd /usr/local
shell> gunzip < /path/to/mysql-VERSION-OS.tar.gz | tar xvf -
shell> ln -s full-path-to-mysql-VERSION-OS mysql
shell> cd mysql
shell> chown -R mysql .
shell> chgrp -R mysql .
shell> scripts/mysql_install_db --user=mysql
shell> chown -R root .
shell> chown -R mysql data
shell> bin/mysqld_safe --user=mysql &

이제 기본 데이터베이스 설치를 위해 아래의 코드 실행. script 디렉토리 안에서 mysql_install_db를 실행하니 아래와 같이 FATAL ERROR가 발생했다. 
그러므로 아래 빨간 색으로 표시된 것처럼 mysql의 탑 디렉토리에서 실행해야 성공한다.

[root@localhost bin]# cd ../scripts
[root@localhost scripts]# ls
mysql_install_db
[root@localhost scripts]# ./mysql_install_db 

FATAL ERROR: Could not find ./bin/my_print_defaults

If you compiled from source, you need to run 'make install' to
copy the software into the correct location ready for operation.

If you are using a binary release, you must either be at the top
level of the extracted archive, or pass the --basedir option
pointing to that location.

[root@localhost scripts]# pwd
/usr/local/mysql/scripts
[root@localhost scripts]# cd ..
[root@localhost mysql]# ./scripts/mysql_install_db 
Installing MySQL system tables...
090720 14:01:07 [Warning] Forcing shutdown of 2 plugins
OK
Filling help tables...
090720 14:01:07 [Warning] Forcing shutdown of 2 plugins
OK

To start mysqld at boot time you have to copy
support-files/mysql.server to the right place for your system

PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !
To do so, start the server, then issue the following commands:

./bin/mysqladmin -u root password 'new-password'
./bin/mysqladmin -u root -h localhost.localdomain password 'new-password'

Alternatively you can run:
./bin/mysql_secure_installation

which will also give you the option of removing the test
databases and anonymous user created by default.  This is
strongly recommended for production servers.

See the manual for more instructions.

You can start the MySQL daemon with:
cd . ; ./bin/mysqld_safe &

You can test the MySQL daemon with mysql-test-run.pl
cd ./mysql-test ; perl mysql-test-run.pl

Please report any problems with the ./bin/mysqlbug script!

The latest information about MySQL is available at http://www.mysql.com/
Support MySQL by buying support/licenses from http://shop.mysql.com/

이제 기본 DB(mysql, test)의 설치가 끝났다. mysql 디렉토리를 보면 data라는 새 디렉토리가 생성되었을 것이다.

mysql 실행
mysql 게정으로 로긴 후
mysql]$ /usr/local/mysql/bin/mysqld_safe &

mysql 종료
mysqladmin -u root -p shutdown

root로 접속하기 (여기서 root는 시스템의 root계정이 아니라, mysql의 관리계정이다)
처음 설치시 root의 패스워드는 없다.

사용형식) mysql -u MySQL계정명 -p 접속할데이터베이스명
mysql]$ mysql -u root -p mysql

database내 테이블 조회
mysql> show tables;

테이블 스키마 조회
mysql> desc <테이블명>;


자동 시작 등록

#!/bin/sh
vi /etc/rc.d/rc.local

/usr/local/mysql/bin/mysqld_safe &

 

- 데몬이 무사히 실행됐다면 서버 시작시에 자동실행되도록 한다.
  # cp /usr/local/mysql/support-files/mysql.server /etc/rc.d/init.d
  # ln -s ../init.d/mysql.server /etc/rc.d/rc0.d/K01mysql
  # ln -s ../init.d/mysql.server /etc/rc.d/rc3.d/S90mysql

 
/var/run/mysqld/mysqld.pid를 생성하지 못할경우
cd /var/run
mkdir mysqld
chown mysql mysqld
chgrp mysql mysqld 



 

'DEVELOPMENT > Linux' 카테고리의 다른 글

linux shell 스크립트  (0) 2012.01.13
Fedora 16 | systemctl - 서비스 관리 명령어  (0) 2011.12.01
ssh 접속 설정.  (0) 2011.11.29
linux 방화벽 열기  (0) 2011.11.29
sftp root 계정 접속 설정  (0) 2011.07.27

Mac에서 Mysql 설치하기

MAC2011. 7. 21. 16:57
 1. mysql-5.5.10-osx10.6-x86_64.dmg 를 다운받는다. (OS 버전에 맞춰)
 2. 마운트하여  mysql-5.5.10-osx10.6-x86_64.pkg 를 설치한다.
 3. mysql 설치 디렉토리는 /usr/local/mysql 이다.
 4. 부팅시 자동으로 시작되게 하려면 MySQLStartupItem.pkg를 추가로 설치한다.
     /Library/StartupItems/MySQLCOM 디렉토리에 설치됨 
     /etc/hostconfig 에 MYSQLCOM=-YES- 로 되어 있으며 자동으로 시작
   MYSQLCOM=-NO- 로 되어 있으면 자동으로 시작되지 않음
 5.  MySQLStartupItem 이 설치되어 잇을 때 서버 start 및 stop
     shell> sudo /Library/StartupItems/MySQLCOM/MySQLCOM start 
     shell> sudo /Library/StartupItems/MySQLCOM/MySQLCOM stop 

 6.  MySQL.prefPane 을 더블클릭하면 시스템환경설정에 추가할 수 있음
      Pane 에서도 자동 시작을 설정할 수 있음 

 [encoding, characterset 적용]

 1. mysql 서버설정을 위한 configuration file 생성
     shell> cd /usr/local/mysql/support-files/ 
     shell> sudo cp my-small.cnf /etc/my.cnf

 2. innodb 로 설정

     [mysqld]
      default-storage-engine = INNODB
      # Uncomment the following if you are using InnoDB tables
      innodb_data_home_dir = /usr/local/mysql/data
      innodb_data_file_path = ibdata1:10M:autoextend
      innodb_log_group_home_dir = /usr/local/mysql/data
      # You can set .._buffer_pool_size up to 50 - 80 %
      # of RAM but beware of setting memory usage too high
      innodb_buffer_pool_size = 16M
      innodb_additional_mem_pool_size = 2M
      # Set .._log_file_size to 25 % of buffer pool size
      innodb_log_file_size = 5M
      innodb_log_buffer_size = 8M
      innodb_flush_log_at_trx_commit = 1
      innodb_lock_wait_timeout = 50

 3. encoding, characterset 서버 환경 설정에 적용 
     
  [mysqld]

  character-set-server=utf8
  collation-server=utf8_general_ci

 4. 트랜잭션 레벨 변경
     오라클의 기본 설정과 같이 READ-COMMITTED 로 적용한다.

[mysqld]
transaction_isolation = READ-COMMITTED

 5. 테이블 대소문자 구분 없이 세팅
     
[mysqld]
lower_case_table_names=1

 6. Auto Commit 설정
     클라이언트 접속시 디폴트는 autocommit=1 이다. 이것을 바꾸기 위해서는 설정파일에 다음과 같이 쓴다.
     0 은 autocommit 을 false 로 세팅한다.

[mysqld]
autocommit=0

 7. client connection characterset 설정
     클라이언트 컨넥션의 디폴트 characterset을 설정한다.

[client]
default-character-set=utf8


 [encoding 에 character set 적용]
 - 데이터 베이스 생성시에 적용 - 해당 데이터베이스에 테이블을 생성할 때 모두 적용됨

      CREATE DATABASE mydb
  DEFAULT CHARACTER SET utf8 
  DEFAULT COLLATE utf8_general_ci; 

 [encoding characterset 확인]
 mysql> use information_schema;
 mysql> select * from GLOBAL_VARIABLES where VARIABLE_NAME like '%CHARACTER%';
 mysql> select * from GLOBAL_VARIABLES where VARIABLE_NAME like '%COLLATION%';
 mysql> select * from GLOBAL_VARIABLES where VARIABLE_NAME like '%AUTOCOMMIT%';

 ※ "Can't get hostname for your address" 에러가 나오면 서버 설정을 해주던지 hosts 파일에 등록한다.
 1. [mysqld]
     skip-name-resolve

 2. mysql 서버 hosts 파일에 mysql 을 호출하는 클라이언트 ip 를 등록

 서버옵션확인
 shell>mysqladmin -uroot -ppassword variables

[출처] http://www.ahnseungkyu.com/60 

'MAC' 카테고리의 다른 글

맥용 유용한 사이트  (0) 2012.01.04
맥 라이언에서 패러럴즈가 실행이 되지 않을 경우  (0) 2011.07.26
[MAC] Mac 응용프로그램  (0) 2011.07.14
[MAC] Mac OS X hosts 파일 수정  (0) 2011.07.14
MAC 단축키  (0) 2011.06.30

* dbname : 데이터베이스명
* dbuser : 사용자 아이디
* dbpassword : 사용자 비밀번호

SHOW DATABASE;
CREATE DATABASE dbname;

USE mysql;

//create user 'username'@'localhost'  identified by 'userpassword';
//create user ' username'@'%'  identified by ' userpassword '; 

INSERT INTO USER(HOST, USER, PASSWORD) VALUES ('localhost', 'dbuser ', PASSWORD('dbpassword'));
INSERT INTO USER(HOST, USER, PASSWORD) VALUES ('127.0.0.1', 'dbuser ', PASSWORD('dbpassword'));
INSERT INTO USER(HOST, USER, PASSWORD) VALUES ('%', 'dbuser ', PASSWORD('dbpassword'));

GRANT ALL PRIVILEGES ON dbname.* TO dbuser@localhost IDENTIFIED BY 'dbpassword';
GRANT ALL PRIVILEGES ON dbname.* TO dbuser@127.0.0.1 IDENTIFIED BY 'dbpassword';
GRANT ALL PRIVILEGES ON dbname.* TO dbuser@'%' IDENTIFIED BY 'dbpassword';  //외부 접속 허용

//GRANT ALL PRIVILEGES ON dbname.* TO 'dbuser'@'localhost' WITH GRANT OPTION;
//GRANT ALL PRIVILEGES ON dbname.* TO 'dbuser'@'127.0.0.1' WITH GRANT OPTION;
//GRANT ALL PRIVILEGES ON dbname.* TO 'dbuser'@'%' WITH GRANT OPTION;


SELECT HOST, USER, PASSWORD FROM USER ORDER BY USER, HOST;

FLUSH PRIVILEGES;

외부에서 접속이 되지 않고 Can't get hostname for your address 라는 메세지가 발생하면 /etc/my.cnf 파일을 열어서
skip-name-resolve 를 추가해주면 된다.

# The MySQL server
[mysqld]
skip-name-resolve


 skip-name-resolve는 client 에서 server로 접속시에 DNS Lookup 과정을 생략해 줍니다. localhost 로 접속하는 경우는 문제가 없지만 IP 로 접속하는 환경에서는 DNS 서버가 느리거나 아님 장애 발생시에 해당 옵션을 설정해 주므로써 DB 접속시에 문제점을 해결하실 수 있습니다.

'DEVELOPMENT > Database' 카테고리의 다른 글

ORACLE 명령문  (0) 2011.08.02
MERGE INTO 사용법  (0) 2011.07.09
오라클 모니터링 SQL  (0) 2011.02.25
Mysql 버전별 DB, USER 생성하기  (0) 2010.12.29
How to install Oracle Client 11g on Windows 7?  (0) 2010.09.27

# 버전별 MySQL user , db , database 생성하기
mysql 버전에 따라서 레코드 숫자가 틀려서 생성 할 때 마다 귀찮은 점이 있다.
적어 두고 생성시 복사해서 사용하는게 편리 하다.
반드시 ID , NAME , DATABASE 이름을 변경하여 사용하시기 바랍니다. 

MySQL 3

create database 데이타베이스명;
insert into user values ('localhost','아이디',password('비밀번호'),'N','N','N','N','N','N','N','N','N','Y','N','N','N','N');
insert into db values ('localhost','아이디','디비이름','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
flush privileges;


MySQL 4

create database 데이타베이스명;
insert into user values ('localhost','아이디',password('비밀번호'),'N','N','N','N','N','N','N','N','N','Y','N','N','N','N','N','N','N','N','N','N','N','','blob','blob','blob','0','0','0');
insert into db values ('localhost','아이디','디비이름','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
flush privileges;


MySQL 5

create database 데이타베이스명;
insert into user values ('localhost','아이디',password('비밀번호'),'N','N','N','N','N','N','N','N','N','Y','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','','blob','blob','blob','0','0','0','0');
insert into db values ('localhost','아이디','디비이름','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
flush privileges;

 


커스텀 설정은 다음과 같은 명령어로 필드 값을 본뒤에 수정 하여 사용할 수 있습니다.
desc user;
desc db;
모든 작업 후 반드시 flush privileges; 로 적용합니다. (모든 작업은 가상으로 작업 된 뒤 적용 시점에 작동 됩니다.)
 

MySQL 데이타 베이스, 삭제하기
      내용 delete from user where user='해당유저이름';
delete from db where db='해당디비이름';
flush privileges; (적용)


사용자 추가

MYSQL에서 유저를 추가하는 방법은 두가지가 있습니다.
일반적으로는 유저를 위한 전용 데이터베이스를 하나 생성해 주고, 해당 데이터베이스에 접속할 권한을 주게 됩니다.
이 때 권한은 local에서만 접속할 권한을 주거나, JDBC등을 이용한다면 외부에서도 접속할 권한을 주어야 합니다.

0.. CREATE DATABASE 명령을 이용한  데이터베이스 신규 생성
1. CREATE USER와 GRANT 명령어 사용 (또는)
2. INSERT, UPDATE, DELETE를 사용해서 직접 관리 테이블을 수정하기를 통한 추가

기존 글을 찾아보면 2번의 내용이 많지만 전문가가 아니라면 개인적으로는 쉬운 1번을 추천합니다. 



먼저 root 유저로 로그인합니다. 암호가 없을 경우 
c:\mysql\bin> mysql -u root mysql

암호가 존재할 경우
c:\mysql\bin> mysql -u root  mysql -p

mysql에 접속한 후에 유저가 사용할 데이터 베이스를 만듭니다. 데이터베이스 명은 ps3_psn 으로 합니다.
mysql> create database ps3_psn; 

먼저 ryu라는 유저를 생성합니다. 암호는 ssf4로 하겠습니다.
mysql> create user 'ryu'@'localhost'  identified by 'ssf4';

ryu 유저에게 ps3_psn 데이터베이스를 로컬에서만 접속할 수 있게 권한을 줍니다.
mysql> GRANT ALL PRIVILEGES ON ps3psn.* TO 'ryu'@'localhost'
    ->     WITH GRANT OPTION;

ryu 유저에게 모든 데이터베이스를 로컬에서 접속할 권합을 준다면
mysql> GRANT ALL PRIVILEGES ON *.* TO 'ryu'@'localhost'

ryu 유저에게 ps3_psn  데이터베이스에 원격에서도 접속할 권한을 줍니다. JDBC 등에서 사용하려면 이런 식으로 합니다.
mysql> GRANT ALL PRIVILEGES ON ps3_psn.* TO 'ryu'@'%'    ->
    WITH GRANT OPTION;

접속권한 보기
mysql> SHOW GRANTS FOR 'ryu'@'localhost';



유저 생성하고 권한 부여하기


1. test 유저를 생성하고 testdb라는 데이터베이스에 모든 권한 부여하기(단, 이 유저는 localhost 에서만 접근 가능하며 접근을 위해서 패스워드 필요)

mysql> grant all privileges on testdb.* to test@localhost identified by '패스워드';



2. test 유저는 모든 호스트에서 testdb에 접근 할 수 있지만 select, insert 권한만 가진다.

mysql> grant select, insert on testdb.* to test@'%' identified by '패스워드';


 3. test 유저는 192.168.0으로 시작하는 모든 컴퓨터에서 접근 가능하며 모든 DB에 모든 권한을 가진다.

mysql> grant all privileges on *.* to test@'192.168.0.%' identified by '패스워드';



 

[출처] http://blog.naver.com/forspeed4?Redirect=Log&logNo=130037742496
[출처] http://k502000.blog.me/30097017893
[출처] http://blog.omyworld.co.kr/entry/Mysql-user-생성-및-권한-부여

개인 프로젝트를 진행하면서 회원 정보 암호화를 하던 중에 알게된 mysql 함수입니다.
mysql에는 몇가지의 암호화가 제공이 되네요.
특정 암호화를 요청하지 않고 단순히 암호화만 요청할 경우 유용하게 사용할수 있을듯 합니다.

password('문자열')
SELECT PASSWORD('anaconda')
-->*75DCB4DD52B015D0F2B46F1AA906E66B008972E5
SELECT OLD_PASSWORD('anaconda')
-->0f9079872dca54d7

encode('문자열', 'key')
/* 암호화 */
SELECT ENCODE('abc', 'key');
-->��
/* 복호화 */
SELECT DECODE(ENCODE('abc', 'key'), 'key');
-->abc

encode 함수를 사용할 경우 data type는 CLOB로 해야 저장이 되네요..

'DEVELOPMENT > Database' 카테고리의 다른 글

Mysql 버전별 DB, USER 생성하기  (0) 2010.12.29
How to install Oracle Client 11g on Windows 7?  (0) 2010.09.27
[mysql] column add, modify, delete  (0) 2010.04.15
[mysql] 날짜 관련 함수  (0) 2010.03.18
[mysql] 문자열 함수[펌]  (0) 2010.03.16