PHP 프로그래밍

PHP 프로그래밍

전남대학교 전자계산소

전남대학교 전자계산소

전남대학교 전자계산소

김 진수

차        례

1. 기본문법

1.1 php 스크립트 선언

1.2 문장(satement)

1.3 주석(comment)

1.4 문자열 다루기

1.5 변수와 데이터 type

1.6 배열

2. 프로그램 흐름 제어

2.1 조건문

2.2 반복문

3. 함수

4. 클래스

5. 파일

6. PHP3를 이용한 홈페이지 만들기

7. 데이터베이스 및 SQL

7.1 DBMS 소개

7.2 SQL 소개

8. MySQL 사용법

9. MySQL과 PHP3 연동

10. 팀 프로젝트

1. 기본 문법

1.1 php 스크립트 선언

html 파일에서 php 스크립트를 사용하기 위해서는 기존의 html tag들과 php 스크립트를 구분할 필요가 있다. html tag과 php 스크립트를 구분하는 방법에는 아래와 같이 4가지 방법이 존재하고 모두 동일한 결과를 출력한다.

방법1>

<?

echo "hello world";

?>

방법2>

<?php

echo "hello world";

?>

방법3>

<script language=php>

echo "hello world";

</script>

방법4>

<%

echo "hello world";

%>

1.2 문장(satement)

php에서 문장은 c나 perl에서처럼 □;□로 끝난다.

사용예>

<?php

echo "안녕하세요□;

echo "php문장은 ;로 끝난답니다□;

?>

1.3 주석(comment)

주석은 프로그램 code에 대한 설명으로 code를 보다 읽기 쉽게 해주는 것으로 실제 프로그램 수행시에는 무시되는 부분이다. php에서 주석은 □//□로 시작하는 부분에서 그 줄 끝까지 주석으로 인식한다.

사용예>

<?php

// 다음은 echo을 사용 합니다.

echo "주석에 대한 예입니다□;

?>

주석을 얼마나 잘 활용하는 것은 프로그램을 잘하고 못하고를 나타는 척도 중 하나이다.

1.4 문자열 다루기

문자열 길이

문자열의 길이를 알기 위해서는 length라는 함수를 사용한다.

형식>

int strlen(문자열);

예>

<?php

$string = "father is Kim";

$count = strlen($string);

header( "Content-type: text/html" );

print "$string의 길이는 $count 입니다\n";

?>

문자열치환

문자열 중 특정한 부분을 찾아 다른 문자열로 바꾸는 데 사용되는 함수이다.

형식>

ereg_replace( "찾는문자□, □바꿀문자열□, 문자열 );

예>

<?php

$string = "father are a farmer";

header( "Content-Type:text/html" );

echo "처음 문자열: $string;

$string = ereg_replace( "are", "is", $string );

echo "치환된 문자열: $string\n";

?>

참고> 대소문자 구분없이 치환하려면 eregi_replace함수를 사용한다.

문자열 분리

텍스트 베이스의 데이터베이스에서는 자료를 저장하는데 □이름&&E-mail$$URL&&내용□과 같이 하나의 줄에 모든 데이터를 특정 기호를 경계로 하여 저장하는 경우가 많이 있다. 이때 경계로 사용된 특수문자와 실제 자료와의 구분에 사용되는 함수가 다음에서 소개되는 split 함수이다.

형식>

split("분리기호□, 문자열);

예>

다음은 □&□기호로 연결된 두 개의 단어를 분리하는 프로그램이다.

<?php

$string = "father&mother";

header( "Content-Type:text/html" );

print "처음 문자열: $string";

$lines = split( "&", $string );

print □분리된 문자열: $lines[0] 과 $line[1]\n";

?>

문자열 찾기

주어진 문자열이 찾고자하는 문자열을 포함하고 있는지 알아내는 구문이다.

형식>

ereg( "찾는 문자열□, 문자열 );

주의>

기본적으로 대소문자를 구분하며 대소문자 구분을 없애려면 □/찾는문자열/i'와 같은 형식으로 해야한다.

예>

<?php

$string = "father";

header( "Content-Type:text/html" );

if( ereg( "th", $string ) ) {

print "$string은 th를 포함하고 있다□; }

?>

1.5 변수와 데이터 type

변수

변수(variable)은 말 그대로 프로그램이 실행하면서 그 값이 변할 수 있는 것을 말한다. php에서 변수는 c언어와 같은 다른 언어에서 변수를 사용하는 방법보다 훨씬 쉽고 간단하다. php에서는 변수가 필요할 때 그때 그때 쓰기만 하면 자동으로 변수가 생성 되고 변수 타입도 특별히 지정해 주지 않아도 대입되는 값에 따라 자동으로 변수 타입이 바뀌게 된다.

변수형식>

$<변수명>

사용예>

<?php

$msg = "안녕하세요! 리눅스 팽귄이어요...□;

$a = 1;     $b = 2;

$c = $a + $b;

echo "<h1>$msg</h1>;

echo "1+2 => $c";

?>

데이터 type

데이터 type이란, 프로그램에서 사용되는 데이터 종류를 말하는데 php에서는 문자열, 정수, 실수, 배열, 객체, pdfdoc등의 데이터 type을 지원한다.

1.6 배열

배열이란 하나의 변수 이름에 같은 종류의 데이터를 동시에 여러개를 저장할 수 있는 변수를 한다. php에서 배열은 array()함수를 이용하거나 순차적인 값을 할당하여 자동으로 배열의 크기를 늘려가는 방법이 있다.

배열생성 예>

1. array()함수를 이용하는 방법

<?php

$flower = array( "장미□, □백합□, □튤립□ );

echo "<h1>";

echo "두번째 꽃은 $flower[1]입니다□;

echo "</h1>";

?>

2. 순차적으로 배열의 크기를 늘려가는 방법

<?php

$flower[] = "장미□;

$flower[] = "백합□;

$flower[] = "튤립□;

echo "<h1><font color=blue>

echo "두번째 꽃은 $flower[1]입니다□;

echo "</font></h1>

?>

배열안에 할당되어 있는 값 참조

배열안에 순차적으로 할당되어 있는 값을 참조하기 위해서는 배열안에서의 순서를 나타내는 첨자라는 숫자나 연상배열에서의 key으로 참조한다. 순서를 나타내는 첨자는 0부터 시작한다.

$car = array( "소나타□, □레간자□, □그랜져□ );

배열이 위와 같이 선언되어 있을 때 □레간자□라는 두 번째 값을 참조하기 위해서는 $car[1]이라고 하면되다. 왜냐하면 배열의 첨자는 0부터 시작하기 때문에 두번째 값은 1로 참조한다.

연상배열(associative array)

연상배열은 배열의 값을 참조하기 위해 첨자를 사용하는 것이 아니라 배열의 값을 가르키는 key값을 사용한다.

사용예>

<?php

$department = array(

"이쁜이□ => □이승하□,

□새침이□ => □김양현□

□멋장이□ => □조일련□

);

echo "이쁜이는 $department[이쁜이]입니다.□;

?>

배열관련 함수

array

배열을 생성하기 위해 사용하는 함수

형식>

array array(...);

함수의 수행 결과 배열이 반환 된다.

사용예>

<?php

$department = array( "전산학과□, "물리학과□, □수학과□ );

?>

array_walk

배열을 인수로하는 함수를 사용하기 위한 함수

형식>

int array_walk( array array_name, string function )

인수: array_name = 배열명,	function = 함수명

결과: 성공/실패

사용예>

<?php

$department = array(

□전산학과□ => "CS",

"물리학과□ => □physics",

"수학과□	=> □math"

);

function array_print( $item ){

echo "$item<br>";

}

array_walk( $department, array_print );

?>

먼저 $department라는 배열을 선언을 하고 array_print라는 함수를 정의한다. 그리고 array_walk( $department, array_print )는 $department 배열의 값을 순차적으로 array_print 함수의 인수로 넘겨준다.

asort

배열을 사용하다보면, 종종 배열의 값을 정렬(sorting)해야하는 경우가 생기는데 이럴 때 사용하는 함수로서 배열의 색인 값은 그대로 유지한 채 배열을 오름차순으로 정렬한다.

형식>

void asort( array array_name );

인수: array_name = 배열명

사용예>

<?php

$deparment = array(

"전산학과□ => □CS",

"물리학과□ => □physics",

"수학과□ => □math" );

function array_print( $item ){

echo "<h2>$item<br></h2>";

}

array_walk( $department, array_print );

asort( $department );

echo "<hr>";

array_walk( $department, array_print );

?>

arsort

배열을 오름차순으로 정렬하는 asort의 역으로 배열을 내림차순으로 정렬한다.

형식>

void arsort( array array_name );

인수: array_name = 배열명

count

변수안에 들어있는 요소들의 개수를 알 수 있는 함수이다.

형식>

int count( mixed var );

인수 = 변수명

결과 = 요수 개수

사용예>

<?php

$deparment = array(

"전산학과□ => □CS",

"물리학과□ => □physics",

"수학과□ => □math"

);

$num = count( $department );	// ---------> (1)

echo "<h1>";

echo "\$department배열의 개수는 ${num}입니다□;	// ---------> (2)

echo "</h1>";

?>

(1)에서 $num은 $department 배열이 가지고 있는 원소의 개수 3을 입력받는다.

(2)에서 ${num}의 {}는 변수명과 다른 문장을 구분하기 위해서 사용한 것으로 그 자체에는 의미가 없다. 그러나 {$num}같이 쓸 경우 □{3}□과 같이 출력되므로 주의해야한다.

current

배열 안에서 유지되는 배열 포인터가 가르키는 요소의 값을 반환한다.

형식>

mixed current( array array_name );

인수:	array_name = 배열명

결과:	요소의 값

each

배열에서 현재 배열 포인터가 가르키고 있는 요소에 대한 키값의 쌍을 반환한다. 반환되는 값은 연상 배열의 형태로서 4개의 키명(0,1,key,value)을 갖는다. 0과 key는 키 값을 표시하고 1,과 value는 요소의 값을 나타낸다.

형식>

array each( array array_name );

인수:	array_name = 배열명

결과:	배열

사용예>

<?php

$dog = array( "바둑이□, □누렁이□, □점순이□ );

$point = each( $dog );

echo "key=$point[0],	value=$point[1]";

echo "key=$point[key],	value=$point[value]";

?>

end

배열 포인터를 배열의 맨 끝으로 이동시킨다.

형식>

end( array array_name );

인수: array_name = 배열명

key

배열로부터 현재 배열 포인터가 가르키고 있는 요소의 key값을 추출한다.

형식>

mixed key( array array_name );

인수: array_name = 배열명

사용예>

<?php

$deparment = array(

"전산학과□ => □CS",

"물리학과□ => □physics",

"수학과□ => □math"

);

$key = key( $department );           // ------> (1)

echo "<h1>";

echo "key=$key,   value=$department[$key]";

echo "</h1>";

?>

(1)에서 $department배열에서 현재 배열 포인터가 가르키는 키값을 추출한다.

ksort

배열의 키 값을 정렬하기 위해 사용하는 함수로서 배열의 요소들의 값은 그대로 놔두고 키 값들만을 정렬한다.

형식>

int ksort( array array_name );

인수: array_name = 배열명

사용예>

<?php

$fruits = array(  "d" => "lemon",  "a" => "orange",

"b" => "banana", "c" => "apple" );

for( reset(

2. 프로그램 흐름제어

2.1 조건문

if 문

조건문이 참이면 참에 해당하는 내용이 실행되고 거짓이면 거짓에 해당하는 내용이 실행된다.

형식1>

if(조건문)

{

}

형식2>

if(조건문){

}

else{

}

형식3>

if(조건문){

}

elsief(조건문){

}

else{

}

switch 문

switch문은 C언어에서 switch 문을 사용하는 방법과 일치한다.  여러 개의 조건 가운데 만족하는 조건을 찾아서 해당 내용을 실행한다.

형식>

switch(조건){

case "찾는값1□ :

실행될 내용

break;

case "찾는값2□ :

실행될 내용

break;

default:	// 조건이 위 case문에 맞는 값이 하나도 없을 때□

실행될 내용

}

2.2 반복문

for 문

반복문으로 해당 조건이 만족하는 동안 실행된다.

형식>

for(시작 ; 종료조건 ; 증분) {

}

예>

<?php

header( "Content-Type:text/html" );

for( $i=1 ; $i<11 ; $i++ ){

print "$i\n";

}

?>

while 문

for문과 마찬가지로 조건이 만족하는 동안 계속 실해되는 반복문

형식>

while( 조건식 ){

}

예>

<?php

header( "Content-Type:text/html" );

$i = 10;

while( $i > 0 ){

echo "$1";

$i = $i - 1;

}

?>

each 문

배열의 요소를 순차적으로 key/value의 쌍으로 배열을 돌려준다.

예>

$foo = array( "a", "b", "c" );

while( $bar = each($foo) ){

echo "$bar[1]";

}

3. 함수

프로그램을 작성하다보면, 프로그램 코드 자체가 중복되는 경우가 있다. 동일한 작업인데, 입력되는 값만 차이가 나는 경우가 바로 이 경우에 해당된다. 이러한 문제를 해결하기 위해서 함수를 사용한다. 함수는 하나의 출력을 갖는 프로그램 문장의 집합으로, 함수명, 함수에 입력될 입력인자들, 그리고 함수를 구성하는 프로그램 코드들로 구성되어 있다. 일반적인 형식은 다음과 같다.

형식>

function <함수명> ( <인자1>, <인자2>, .... ) {

// 함수를 구성하는 코드

}

PHP에서 함수는 반드시 fucntion으로 시작하며, 뒤이어 사용자 정의 함수명이 위치한다. 함수명은 변수명과 동일한 형태를 갖는다. 다음으로 함수에 입력된 인자들이 위치하는데, 이러한 인자들의 대부분은 변수명이 위치한다. 함수는 □{□와 □}□를 사용하여 함수가 정의된 영역을 표시한다. 이 영역 안에 함수에서 수행해야 할 코드를 입력하면 된다.

위의 함수는 함수의 수행 결과를 반환하지 않는 경우를 표시한 것으로, 이러한  함수를 서브루틴이라고 한다. PHP에서 함수의 수행 결과를 반환하는 본래 의미의 함수 구현은 다음의 형식을 따른다.

function <함수명> ( <인수1>, <인수2>, ... ) {

// 함수를 구성하는 코드들

return <반환할 값을 저장하는 변수명이나 수식>;

}

위와 서브루틴과의 차이점이란 함수를 구성하는 코드의 맨 마지막 줄에 rturn이라는 PHP의 고유어를 쓰고, 반환할 값이나 변수, 수식 등을 기술하면 된다. 함수의 사용 예제는 다음과 같다.

<?php

function my_sqrt( $num ) {

return $num * $num;

}

echo my_sqrt(4);

?>

지금까지는 함수의 사용 형식에 대해서 살펴보았고, 지금부터는 함수로 값을 전달하는 방법을 중심으로 살펴보자. 함수에 입력 인수로 값을 전달하는 방법에는 call by value와 call by reference, default argument value가 있다. □call by value'란 함수의 입력 인수로 전달된 값이 함수의 입력 인수에 복사되어 사용되는 것이다. 다음 예를 살펴 보자.

<?php

function print_msg( $msg ){

$msg = "testing message";

echo "함수(수행중) -> $msg";

};

$my_msg = "Hello"

print_msg( $my_msg );

echo "함수(수행후) -> $my_msg";

?>

print_msg() 함수의 인수로서 □hello"라는 문자열을 포함하는, $my_msg라는 변수가 전달된다. 이런한 변수 값은 print_msg() 함수의 입력 인수인 $msg에 보가되어 함수에서 사용된다. 함수를 수행하는 동안과 수행하는 동안과 수행한 후의 값이 일치하지 않는 것을 알 수 있다.  따라서 함수의 입력 인수로 전달된 값은 함수가 사용되는 동안 내부적으로 값이 변동되지 않는다는 것을 알 수 있다. 이러한 방식을 'call by value'라고 한다.

반면 □call by reference'란 □참조에 의한 호출□ 로서, 함수의 입력 인수로 전달된 변수 값이 함수 내부에서의 변경 사항을 그대로 반영하도록 호출하는 방식이다. 위의 코드를 □call by value'방식으로 변경해보자.

<?php

function print_msg( &$msg ){

$msg = "testing";

echo "함수(수행중) -> $msg";

};

$my_msg = "hello";

print_msg( $my_msg );

echo "함수(수행후) -> $my_msg";

?>

프로그램의 수행 결과로 출력된 문장이 함수의 수행중이나 수행 후 모두 동일함을 알 수 있다. 함수의 입력 인수가 함수 내부에서 사용되어 함수 내부의 처리 결과에 반영되기를 원한다면, 입력 인수를 □참조에 의한 호출□ 방식으로 전달해야 한다. 마지막으로, 함수의 입력 인수에 □디폴트값(기본값)□을 설정하는 방법에 대해서 살펴보자. 경우에 따라서 함수의 입력 인수 값으로 고정된 값이 사용되는 경우가 있다. 이런 경우, 함수의 입력 인수로 매번 고정된 값을 전달하는 것은 불필요한 일일 것이다. 이러한 경우에는 함수의 입력 인수에 디폴트값을 설정하면 된다. 사용 예는 다음과 같다.

<?php

$cnt = 0;

function set_value($base=0) {

$cnt=$base;

};

$cnt = 4+5;

set_value();	//$cnt = 0

echo "$cnt";

set_value(35);

$cnt += 10;

echo "$cnt";

?>

위의 예에서는 $cnt 변수 값을 함수의 입력 인수로서 주어진 값으로 설정하기 위해서 set_value()라는 함수를 정의하였다. 이 함수의 입력 인수인 $base는 디폴트 값으로 0을 갖는다. 따라서 만일 0의 값으로 $cnt 값을 설정하고 싶다면, 아래의 함수와 같이 입력 인수 값을 설정할 필요 없이 함수를 호출하면 된다.

set_value();

이러한 함수를 호출하면, 자동적으로 함수의 입력 인수의 $base 값은 0으로 간주되고 $cnt 값을 0의 값으로 설정하게 된다. 아래의 함수는 set_value()함수의 입력 인수 값으로 0이 아닌 다른 값을 사용하는 경우이며, 여기서는 35를 $cnt의 값으로 설정한다. 프로그램의 수행 결과로 각기 다른 $cnt 값을 출력하게 된다.

set_value(35);

변수의 범위(scope)

앞에서 설명했듯이, 변수가 갖는 값의 유형은 변수가 사용되는 문맥에 의해서 결정된다. 이러한 문맥은 문장 수준에 한정된다. 이러한 문장 수준 이외에 변수가 의미 있게 사용될 수 있는 범위가 있다. 이것이 □변수의 범위□이다.

PHP에서 일반적으로 변수는 단일 범주를 갖는다 이 말은 한번 변수가 선언되면 프로그램이 수행되는 동안 PHP 프로그램의 어떠한 부분에서도 그 변수의 값을 사용할 수 있다는 의미이다. 그거나 이러한 변수의 범주에서 예외가 있다. 그 예외가 사용자 정의 함수 내에서 선언된 변수이다. 사용자는 반복되는 작업에 대한 코드 작성의 중복을 피하기 위해서 반복되는 작업을 함수형태로 작성한다. 함수 내에서 정의된 변수들의 생명 주기는 함수가 정의된 □{□와 □}□안의 영역이 된다. 이러한 함수 내에서 정의된 변수를 지역변수(local variable)라고 하고, 프로그램 전체에서 사용할 수 있는 변수를 전역변수(global variable)라고 한다. 용어에서 의미한 바와 같이, 지역변수는 생성과 소멸이 지역적으로 한정되는 반면, 전역변수는 프로그램이 동작할 때 생성되어 프로그램이 종료할 때 소멸된다.

다음으로, static 변수에 대해서 알아보자. satic 변수는 함수 내에서만 정의된다. 지역변수와의 차이점은 지역변수는 함수가 종료하면 지역변수의 값이 소멸되지만, static으로 선언된 변수의 값은 소실되지 않고 유지된다. 함수의 재호출 시에 함수 내에서의 변수 값을 초기화하지 않고, 이전에 사용된 값부터 사용하고 싶다면 해당변수 값을 static 유형으로 선언하면 된다. 다양한 변수의 사용 예를 살펴보자.

<?php

$a = 1; // 전역변수 $a

function add( $op1, $op2 ){

global $a;	// $a가 전역변수임을 선언한다.

$b = $op1 + 4op2;

echo "print_sum1 = $a";

};

add(3, 5);

echo "print_sum2 = $a";

?>

위 예제는 전역변수를 함수 내에서 사용하는 예이다. 함수 내에서 전역변수를 사용하기 위해서는 함수명 밑줄에 golobal 이라는 선언을 변수명 앞에 선언해야 한다. 이렇게 함으로써, 함수 내의 프로그램들은 해당 변수를 전역변수로서 처리하게 된다. 위의 프로그램의 수행 결과 print_sum1과 print_sum2의 출력 결과가 동일한 값인 8을 가지게 된다.

<?php

$a = 1;  //전역변수 $a

function add( $op1, $op2 ) {

$a = $op1 + $op2;	// $a는 지역변수

echo "print_sum1 = $a";

};

add( 3, 5 );

echo "print_sum2 = $a";

?>

위의 예제는 전역변수와 동일한 지역변수명을 사용한 예이다. 함수 add()안의 $a는 지역변수로 취급된다. 왜냐하면 $a 앞에 global과 같은 선언이 없으므로 PHP3에서는 이러한 변수를 모두 함수 내에서만 사용 가능한 지역변수로 취급하게 된다. 따라서 print_sum1과 print_sum2의 출력 결과가 다른 값을 가지게 된다. print_sum1의 출력뭉은 add() 함수로 전달된 두 개인 인수 값을 더한 8을 출력하고 print_sum2는 전역변수 $a의 값인 1을 출력한다.

<?php

function inc() {

static $a = 0;	// 지역변수 $a

$a++;

echo "sum = $a";

};

inc();

inc();

}

위 프로그램은 inc()함수 내에서 static 변수 $a를 정의하고, 이 함수가 호출될 때마다 자동적으로 함수 내의 static 변수 $a의 값을1씩 증가시키는 프로그램이다. 매 호출에 따라서 이전 값에 1을 더한 값을 출력한다.

static 변수 $a는 inc() 함수가 처음 호출될 때 한번만 생성되며, 0값으로 초기화된다. 이후에 inc() 함수를 재 호출해도 $a 변수는 생성되지 않는다. static으로 선언된 변수의 수명은 static 변수를 포함하고 있는 함수의 호출 시에 생성되며, 프로그램이 종료될 때까지 유지된다.

4. 클래스

PHP에서는 클래스를 지원한다. 이러한 점은 C++과 유사한 특징을 갖는다. PHP에서 클래스를 선언하는 방법과 클래스에 대한 객체를 생성하는 방법에 대해서 살펴보자.

Hello 라는 클래스를 만들고, Hello 클래스의 print_msg()라는 함수를 출력하는 예제는 다음과 같다.

<?php

// 클래스를 정의한다.

class Hello {

function print_msg(){

$msg = "hello php3";

echo $msg;

};

};

// 클래스에 대한 객체를 생성한다.

$var = new Hello;

// 생성된 클래스에 대해서 함수를 생성한다.

$var -> print_msg();

?>

5. 파일

다음은 파일 관련 함수들이다.

basename

경로명으로부터 파일명을 얻기 위해서 사용하는 함수

<형식>

string basename( string path );

예>

$path = "/home/httpd/html/index.php3";

$file = basename( path );  // $file is set to "index.php3"

copy

한 파일의 내용을 다른 파일명으로 복사하는 함수

형식>

int copy( string source_file, string dest_file );

예>

if( !copy($file, $file . '.bak') ){

print( "failed to copy $file..<br>\n" );

}

dirname

경로명에서 파일명을 제외한 디렉토리 경로를 얻기 위해서 사용된다.

형식>

string dirname( string path );

예>

$path = "/etc/paswd";

$directory = dirname( $path );

fclose

열려진 파일을 닫기 위해 사용하는 함수

형식>

int fclose( int fp );

함수의 입력인수로 파일 포인터 값이 위치하며, 함수의 수행 결과 정상적으로 파일이 닫혀졌을 경우 1의 값을 반환한다. 비정상적으로 파일이 닫혀지면 0의 값을 반환한다.

feof

열려진 파일의 끝인가를 테스트하기 위이해서 사용하는 함수

형식>

int feof( int fp );

입력변수로 파일의 포인터가 위치하며, 파일 포인터가 EOF를 가리키면 참의 값을 반환한다.

fgetc

파일로부터 문자단위로 읽어들이기 위해서 사용하는 함수.

형식>

string fgetc( int fp );

입력 인수로 파일 포인터가 위치하며, 함수의 수행 결과, 파일로부터 읽혀진 문자를 포함하는 string이 반환된다. 만일 파일의 끝에 도달하면 False가 반환된다.

fgets

파일로부터 지정된 바이트 수만큼의 문자열 길이로 읽어들이기 위해서 사용하는 함수로, 사용 형식은 다음과 같다.

형식>

string fgets( int fp, int length );

두 개의 입력인수를 사용하는데, fp는 파일의 포인터를 나타내며, length는 파일로부터 읽어들일 바이트 수를 나타낸다. 수행 결과, 지정된 길이( 최대 길이는 length-1 )만큼의 바이트가 읽혀진다. 오류가 발생되면 함수의 결과로 false가 반환된다.

fgetss

HTML 문서를 읽어들여서 처리할 경우에 유용한 함수로, 사용 형식은 fgets 함수와 동일하지만 한가지 차이점이 있다. 지정된 바이트 수만큼의 문자를 읽어들인 후, 읽어들인 문자들 가운데에서 HTML 관련 태그들을 제거하는 기능이 제공된다.

형식>

string fgetss( int fp, int length );

file

파일 전체 내용을 하나의 배열에 읽어들이기 위해서 사용하는 함수로, 사용 형식은 다음과 같다.

형식>

array file( string  filename );

입력인수로 파일명이 위치한다. 함수의 수행 결과, 주어진 파일명에 포함된 내용 전체를 담고 있는 배열이 반환된다. 이 함수를 사용하면 파일에 내용을 읽어서 처리하기 위해 파일 관련 함수를 사용할 필요 없이 배열을 처리하는 형식으로 파일을 다룰 수 있게 된다.

file_exists

파일의 존재 여부를 체크하기 위해서 사용하는 함수.

형식>

int file_exists( string filename );

함수의 입력 인수로 파일명이 위치한다. 함수의 수행 결과, 파일이 존재하면 true 값이 반환되고, 그렇지 않으면 false 값이 반환된다.

filesize

파일의 크기를 얻기 위해 사용되는 함수

형식>

int filesize( string filename );

byte 단위의 파일 크기를 돌려준다.

filetype

파일의 유형 정보를 얻기 위해서 사용하는 함수

형식>

string filetype( string filename );

함수의 입력 인수로 파일명이 위치하고, 함수의 수행 결과로 파일의 유형 값이 반환된다. 가능한 파일의 유형에는 fifo 와 char, dir, block, link, file, unknown 타입이 가능하다.

fopen

파일을 열거나 URL을 열기 위해서 사용하는 함수

형식>

int fopen( string filename, string mode );

함수의 입력 인수로는 두 개가 위치하는데, filename은 함수의 이름이나 URL명에 위치하며, mode는 열려진 문서의 형식을 지정하기 위해서 사용된다. 파일이 정상적으로 오픈 되었다면 true 값이 반환되고, 오류가 발생하면 false 값이 반환된다. 오픈할 파일의 문서 형식으로는 r, w, r+, w+, a, a+ 등 6개가 가능하다. r은 read only를 말하며, 전적으로 익기 용도로 오픈할 파일임을 표시한다. r+는 읽기와 쓰기를 동시에 수행할 파일임을 나타낸다.

w는 쓰기 전용의 파일을, w+는 쓰고 읽기 위한 용도로 파일을 오픈한다는 의미이다. a는 append를 말하며, 파일의 뒷부분에 덧붙인다는 의미이다. a는 전적으로 쓰기 용도로 오픈한다는 의미이고, a+는 읽고 쓰기 위한 용도로 오픈한다는 의미이다. r+(w+)와 a+의 차이점은 r+(w+)는 파일 오픈시 파일의 포인터를 파일의 맨 처음에 위치시키지만, a+는 파일의 맨 뒤에 위치시킨다는 점이 다르다. 사용 예제는 다음과 같다.

$fp = fopen( "/home/rasmus/file.txt", "r" );

$fp = fopen( "http://www.php.net/", "r" );

fputs

문자열을 파일에 쓰기 위해서 사용하는 함수

형식>

int fputs( int fp, string str, int [length] );

함수의 입력으로 두 개의 인수들과 하나의 선택적인 인수가 사용된다. fp는 파일의 포인터를 지칭하며, str은 파일에 쓸 문자열을 담고 있는 변수명을 지칭한다. 마지막 length는 문자열의 길이로, 이 값은 선택사항이다. 기입하지 않으면 자동적으로 str의 길이가 지정된다.

fread

지정된 길이 만큼 파일에서 읽어 드린다.

형식>

string fread( int fp, int length );

함수의 입력으로는 두 개의 인수가 사용되는데, fp는 파일 포인터를 지칭하며, length는 파일로부터 읽어들인 byte 수를 표시한다. 이 함수는 현재의 파일 포인터부터 시작하여 지정된 byte 수만큼의 문자를 읽어들여 문자열의 형태로 반환한다.

예>

$filename = "/usr/local/something.txt";

$fd = fopen( $filename, "r" );

$contents = fread( $fd, filesize( $filename ) );

fclose( $fd );

fseek

파일로부터 특정 위치로 이동하기 위해서 사용하는 함수.

형식>

int fseek( int fp, int offset );

함수의 입력인수는 두 개가 사용되는데, fp는 파일 포인터 자체를 나타내며, offset은 파일 포인터가 이동할 바이트 수를 표시한다. 동작이 제대로 이루어지면 0의 값을 반환하고, 그렇지 않으면 -1을 반환한다.

ftell

파일 내부에 유지되는 파일 포인터의 현재 위치를 알기 위해서 사용하는 함수

형식>

int ftell( int ftp);

입력인수: fp = 파일 포인터

fwrite

일정한 길이만큼의 데이터를 파일에 쓰기 위해서 사용하는 함수

형식>

int fwrite( int fp, string string, int [length] );

입력인수: fp = 파일 포인터 , string = 입력할 문자열을 담고 있는 변수명, length =  문자열 길이( 지정되지 않으면 자동으로 string의 길이가 들어간다. )

mkdir

디렉토리 생성을 위해서 사용되는 함수

형식>

int mkdir( string pathname, int mode );

입력입수: pathname = 디렉토리 경로명, mode = 접근 권한

pclose

파이프(pipe)를 닫기 위해서 사용하는 함수

형식>

int pclose( int fp );

입력인수: fp = 파일포인터

popen

프로세스에 대한 파이프를 열기 위해서 사용하는 함수

형식>

int popen( string command, string mode );

입력인수 : command =  수행될 프로세스를 위한 명령어, mode = 파이프 연결상태 지정.

예>

$fp = popen( "/bin/ls", "r" );

readfile

파일내용을 읽어서 표준출력(standard output)으로 출력하기 위해서 사용되는 함수

형식>

int readfile( string filename );

입력인수로 파일의 이름이 주어지며, 함수의 수행 결과 파일로부터 읽어들인 문자들의 개수가 반환된다. 수행 도중에 오류가 발생되면, false 값이 반환된다.

rename

파일이름을 바꿀 때 사용하는 함수

형식>

int rename( string oldname, string newname );

oldname은 이전 파일명이고 newname은 새로운 파일명이다. 정상적으로 완료되면 true 값이 반환되고 그렇지 않으면 false가 반환된다.

rewind

open된 파일 내에서 파일 포인터를 시작위치로 이동 시킨다.

형식>

int rewind( int fp );

입력 인수로는 파일의 포인터가 위치하며, 함수의 수행결과 정상적으로 수행되면 1이  실패하면 0이 반환된다.

rmdir

디렉토리 삭제를 위해서 사용되는 함수

형식>

int rmdir( string dirname );

입력인수: dirname = 삭제할 디렉토리명

6. PHP3를 이용한 홈페이지 만들기

[프로그램1]

내용>

php 맛만 보여주는 html 문서

1: <?php

2: // html 테스트 페이지 만들기

3: // html 문서 형식을 지정하는 header 함수

4: header( "Content-Type: text/html" );

5:

6: echo □<html><head><title>php text</title></head>\n";

7: echo "<body bgcolor=FFFFFF>\n";

8: echo "<center>";

9: echo "<h1>PHP HTML 문서 만들기</h1>\n"

10: echo "php를 이용하여 html 텍스트 페이지를 만듭니다. <p>\n";

11: echo "이 화면이 보이면 php가 정상적으로 작동하므로 cgi가 가능합니다.\n";

12: echo "<hr></center>\n";

13: echo "</body></html>\n";

14: exit;

15: ?>

4번 줄에 있는 header 함수는 위문서의 mime-type을 알려주는 헤더 라인입니다.

6~13번째 줄에 있는 echo는 print와 거의 같은 기능을 가지고 있다. echo는 한 줄 이상의 문자열을 출력하는데 이용되고 print는 한 줄의 문자열을 출력하는 함수이다. 여기에 echo 대신에 print를 사용하여도 결과는 같습니다.

14번 줄의 exit는 php 프로그램의 종료를 나타냅니다.

[프로그램2]

내용>

홈페이지 방문자가 첫 페이지에서 자신의 이름과 주소를 입력하면 다음화면에 그 결과와 함께 방문자의 IP 어드레스를 보여준다.

1.  방문자의 이름과 주소를 입력받는 폼 파일 작성(comin.html)

2. comin.html에서 전달받은 데이터를 화면에 보여주는 php파일 작성 ( comin.php3 )

3. comin.php3와 똑같은 기능을 하지만 내부적으로 함수를 사용하는 예를 보여준다.

프로그램 작성>

1. comin.html : 방문자의 이름과 주소를 입력받는 html 파일

<html>

<head>

<tittle>방문자 확인 문서</titile>

</head>

<body bgcolor=ffffff>

<center>

<h2>방문자 확인</h2>

아래에 방문자님의 이름과 주소를 입력하세요...!<p>

<form method=post action=comin.php3>

<table>

<tr>

<td>이름</td><td><input type=text name=username size=10></td>

</tr>

<tr>

<td><td>주소</td><td><input text=text name=address size=30></td>

</tr>

<tr>

<td colspan=2 align=center><input type=submit value="데이타 입력□></td>

</tr>

</table>

</form>

</body>

</html>

2. comin.php3 : 사용자가 입력한 username과 address 그리고 IP를 보여주는 php프로그램.

1: <?php

2: //php 프로그램 시작

3: // 방문자 확인 프로그램

4: $IP_ADDRESS = ${'REMOTE_ADDR'};

5: header( "Content-Type:text/html" );

6: echo "

7: <html>

8: <head><title>방문자 확인</title></head>

9:

10: <body bgcolor=#ffffff>

11: <center>

12: <h2>방문자 확인</h2>

13: <table bgcolor=#FCEEEE>

14: <tr>

15: <td>귀하의 IP ADDRESS</td><td>$IP_ADDRESS</td>

16: </tr>

17: <tr>

18: <td>귀하의 이름</td><td>$username</td>

19: </tr>

20: <tr>

21: <td>당신의 주소는</td><td>$address</td>

22: </tr>

23: </body>

24: </html>

25: ";

26: exit;

27:

28: ?>

- 4번 줄에서 사용한 ${REMOTE_ADDR} 은 접속한 사용자의 IP주소를 가지고 있는 PHP 자체에서 제공하는 변수이다.

- 5번 줄에 header 함수는 html 문서의 mime type을 선언한다.

- 26번 줄은 php 프로그램의 종료를 나타낸다.

3. comin.php3와 똑같은 기능을 하지만 내부적으로 함수를 사용하는 예를 보여준다.

1:  <html>

2:  <head><title>방문자 확인</title></head>

3:

4:  <?php

5:  function write( $name, $address, $ip ){

6:  echo "

7:          <center>

8:          <h2>방문자 확인</h2>

9:          <table bgcolor=#FCEEEE>

10:         <tr>

11:         <td>귀하의 IP ADDRESS</td><td>$IP_ADDRESS</td>

12:         </tr>

13:         <tr>

14:         <td>귀하의 이름</td><td>$username</td>

15:         </tr>

16:         <tr>

17:         <td>당신의 주소는</td><td>$address</td>

18:         </tr>

19:         </table>

20: ";	// echo 종료

21: };	// function 종료

22: ?>

23: <body bgcolor=#ffffff>

24: <?php

25:         $IP_ADDRESS = ${REMOTE_ADDR};

26:        write( $username, $address, $IP_ADDRESS );   // 위에서 선언한 write함수 사용

27:  ?>

28: </body>

29: </html>

- 5번 줄에서 write 라는 함수를 선언하고 26번 줄에서 선언된 write 함수를 사용하고 있다.

- 5번 줄에서 write함수 선언시 사용되는 $username, $address, $ip는 프로그램 다른 곳에서 사용되는 변수들과는 전혀 상관이 없다.

7. 데이터베이스 및 SQL

7.1 DBMS 소개

7.1.1 데이타베이스 관리 시스템(database management system:DBMS) 이란.

상호연관이 있는 데이터들의 모임 그리고 그 데이터들을 액세스하기 위한 프로그램의 집합으로 구성된다. 이러한 데이터의 모임을 데이터베이스라고 하고 어떤 특정한 조직에 대한 정보를 가진다. 데이터베이스 관리 시스템의 목적은 데이터베이스내의 정보를 검색하거나, 데이터베이스에 정보를 저장하는데 편리하고 효율적인 환경을 제공하는 것이다. 데이터베이스 시스템은 대량의 정보를 관리하도록 설계되어있다.

7.1.2 DBMS의 목적

영구적 시스템 파일에 고객과 고객의 저축예금 계좌에 과한 정보를 보관하는 은행업무를 생각해 보자. 더 나아가, 시스템은 이들 파일을 조작하기 위해 많은 응용 프로그램을 가지고 있다.

- 계좌의 입금 또는 출금을 처리하기 위한 프로그램

- 새로운 계좌를 추가하기 위한 프로그램

- 계좌의 잔고를 검색하기 위한 프로그램

- 월별 보고서를 작성하기 위한 프로그램

이러한 응용 프로그램들은 은행 조직의 요구를 만족시키기 위해 시스템 프로그래머가 작성한다. 필요에 따라 새로운 요구가 발생하면 새로운 응용 프로그램을 첨가해야 한다. 예를 들어, 저축예금 계좌를 입금하는 은행에서 당좌예금 계좌를 취급해도 좋다는 법규가 새로 제정되었다고 하자, 그러면 모든 은행에서는 당좌예금 계좌에 관한 정보를 수록한 새로운 파일을 만들어야한다. 새로운 응용 프로그램을 작성해야 할 필요가 생길지도 모른다. 이와 같이 시간이 경과함에 따라 새로운 파일이나 응용프로그램이 점차적으로 시스템에 첨가된다. 이상에서 기술한 전형적인 파일 처리 시스템(file-processing system)은 운영체제가 지원한다. 이러한 경우에는 레코드가 여러 개의 파일에 저장되는 경우도 생기며, 레코드를 파일에서 추출한다든지 파일에 첨가하는 프로그램들이 서로 다르게 여러 개 작성되는 일도  생길 수 있다.

파일기반 시스템의 단점

- 데이터의 비 일관성(Data Inconsistency)

- 데이터 액세스의 어려움

- 데이터의 고립(Data Isolation)

- Traction 처리의 어려움

- Sercurity 문제

- 무결성

7.1.3 데이터베이스의 종류

- 구조적 데이터베이스(hierarchical database)

- 네트워크형 데이터베이스(network database)

- 관계형 데이터베이스(relational database)

- 객체기반 데이터베이스(object oriented database)

구조적 데이터베이스와 네트워크형 데이터베이스는 물리적인 프로그램 구현에 더욱 관련이 있는 반면, 관계형 데이터베이스와 객체기반 데이터베이스는 사용자가 데이터를 접근할 때 보다 논리적(logical)으로 접근이 가능하다.

여기서는 현재 대규모 기업 데이터 관리에서부터 소규모의 개인 데이터관리까지 광범위하게 사용되고 있는 관계형 데이터베이스에 대해 공부를 한다.

7.1.4 관계형 데이터 베이스 구조

데이터베이스는 테이블들의 집합으로 구성되며 각 테이블은 인스턴스(instance)로서 레코드들로 구성되며 레코드는 속성으로 이루어진다.

가령, 은행 데이터베이스를 예로 들어보자.

은행 데이터베이스에는 간단히 고객들의 정보를 담은 테이블과 계좌정보를 담은 테이블 등 두 개의 테이블를 구성되어 있다고 가정하자.

은행 데이터베이스

- 고객 테이블(Customer)

- 계좌 테이블(Account)

고객 테이블 구조(sheme)

이름	고객번호	주소	전화번호

이때, 이름, 고객번호, 주소, 전화번호는 고객 테이블의 구조(sheme)가 되고, 각각은 고객 테이블의 속성이 된다.

고객 테이블 내용

홍길동	080-2524	광주 용봉동	530-2525
홍길순	080-2525	광주 월산동	525-2335
...	...	...	...

위와 같이 고객 테이블의 내용을 이루는 각 줄을 레코드 또는 튜플이라고 한다.

계좌 테이블 구조(scheme)

계좌번호	지점명	고객번호	예금액

계좌번호, 지점명, 고객번호, 예금액은 계좌 테이블의 구조(scheme)를 이루고 각각은 테이블의 속성이 된다.

계좌 테이블 내용

080-2524-01	용봉점	080-2524	100,000
080-2525-01	전남대점	080-2525	50,000
090-7089-02	오치점	090-7089	1000,000
...	...	...	...

1) 데이터베이스 스키마(schema)

데이터베이스의 스키마란 데이터베이스의 논리적인 설계를 의미한다. 즉, 어떤 조직의 정보를 담고 있는 데이터 베이스가 어떤 종류의 테이블들로 구성되고 그 각각의 테이블들은 어떤 내용으로 구성되어야 하는지를 나타낸다.

데이터베이스 인스턴스

일정 시간동안 데이터베이스에 실제로 들어있는 데이터를 의미한다. 즉, 스키마에서 정의한 구조를 실제로 채우는 내용을 의미하다. 테이블에서 레코드들이 테이블의 인스턴스가 된다.

2) 키(key)

테이블 내에 있는 각각의 레코드를 서로 구분시킬 수 있는 속성들의 집합을 말한다. 예를 들면, 학생들의 정보를 가지고 있는 테이블이 있고, 이 테이블이 다음과 같이 정의되어 있을 때 key값은 학번 또는 주민등록번호가  될 수 있다. 왜냐하면, 학번은 주민등록번호로 모든 학생들을 구분할 수 있기 때문이다, 만일 학번이 두 명 이상이 공유할 수 있다고 가정한다면, 학번은 물론 key가 될 수가 없을 것이다.

이 름	학 번	주민등록번호	학 과

[ key의 종류 ]

- 수퍼키(super key)

레코드들을 구분할 수는 있지만 필요 이상의 키들을 포함하고 있을 수 있	다.

- 후보키(candidate key)

레코드들을 구분하면서 구분에 꼭 필요한 속성들만 포함하고 있다.

- 주키(primary key)

후보키들 중에서 데이터베이스 설계자가 각 레코드들을 구별하기 위해 선	택한 키를 주키(primary key)라고 한다.

7.2 SQL (Structured Query Language) 소개

7.2.1 SQL이란.

SQL은 1970년대 초에 IBM에서 개발된 후 메인 프레임은 물론이고 다양한 워크스테이션과 pc에 이르기까지 수많은 시스템에서 사용되고 있는 관계형 데이터베이스 처리용 언어이다. 데이터 베이스상의 질의를 처리하기 위해 여러 가지 언어가 존재하지만, 현재에는 1992년에 발표된 SQL/92가 국제 표준으로 인정받고 있다. 하지만 SQL/92의 표준을 완벽하게 지원하고 있는 상용 데이터베이스 시스템은 없다고 볼 수 있을 정도로 방대한 규모를 가지고 있는 언어이기도 하다.

7.2.2 SQL의 기능의 따른 분류

1.DML(Data Manipulation Language)

데이터베이스로부터 원하는 레코드들을 검색하거나, 레코드의 삽입, 삭제, 갱신, 테이블끼리의 결합(join)등 데이터베이스에서 주로 데이터 처리부분을 담당하는 언어이다.

2.DDL(Data Definition Language)

데이터베이스에 새로운 테이블을 추가하거나, 테이블에 색인(index) 혹은 필드 등을 추가, 변경하는 등, 데이터 정의부분과 관련된 언어

7.3 DML (Data Manipulation Language)

7.3.1 DML의 종류

- SELECT: 데이터베이스에서 원하는 데이터를 추출해 낸다.

- INSERT: 테이블에 레코드를 추가한다.

- DELETE: 테이블로부터 레코드를 삭제한다.

- UPDATE: 테이블상의 레코드들을 갱신한다.

- 집합형 함수( SUM,AVG,MIN,MAX,COUNT.. )

- 연산자( IS NULL, IS NOTNULL,, )

<tip>

SQL의 모든 예약어는 대소문자를 구분할 필요는 없다. 그러나 관습상 예약어는 보통 대문자로 표기하는 것이 보통이다.

7.3.2 SELECT문

select문은 데이터베이스로부터 원하는 데이터들을 검색하기 위해서 사용한다.

형식>

SELECT <field1>, <field2>, ...

FROM	<table1>, <table2> ,,,

WHERE <조건>

SELECT절은  Table에서 추출하고자 하는 field들을 나열한다.

FROM절은 Query작업의 대상이 되는 Table들을 나열한다.

WHERE절은 데이터를 추출하고자 하는 조건들을 적어준다.

예1>

어떤 백화점에서 고객들의 데이터베이스에서 바겐세일 안내를 위해서 고객들의 이름과 주소를 추출하려고 한다. 이때 고객들의 데이터를 보관하고 있는 테이블이 Customer라고 하고 고객들의 이름을 Client_Name 그리고 고객의 주소를 Address 이라고 할 때, 고객들에 대한 정보를 추출해내는 Query문은 다음과 같다.

SELECT Client_Name, Address

FROM	Customer;

예2>

예1>에서 고객의 구입액을 Buy_Amount라고 할 때 구입액이 50만원 이상인 고객에게 바겐세일 안내를 보내는 Query는 WHERE절에 조건을 줌으로써 원하는 데이터들만 추출해 낼 수 있다.

SELECT Client_Name, Address

FROM	Customer

WHERE Buy_Amount >= 500000;

7.3.3 Order By 절을 이용한 레코드 정렬

때에 따라서 Query 결과를 특정한 필드의 값에 따라 정렬하고자 할 때도 있다. 주어진 결과를 특정한 순서로 정렬하고자 할 때 사용하는 것이 바로 Order By절이다. 기본적으로 올림차순으로 정렬되며, 내림차순으로 정렬하고자 하면 필드 이름 뒤에 DESC를 추가해야 한다.

예1>

고객 테이블 Customer에서 고객번호 Client_Num가 7000번 이하인 고객들만 추출하되 Address 필드를 이용해서 결과를 정렬하라.

Select Client_Name, Address

From Customer

Where Client_Num <= 7000

Order by Address;

Select절 다음의 Client_Name, Address는 Customer 테이블에서 추출하고자하는 필드들이고 From절의 Customer는 작업대상 테이블이다. Where절의 □Client_Num <= 7000' 은 추출을 원하는 데이터들의 조건이 된다.

예2>

고객 테이블에서 고객번호인 Client_Num가 7000번 이하인 고객들만 추출하되 원하는 필드들은 Client_Name, Address, Buy_Amount이다. 이때 추출한 결과를 Address로 1차 정렬을 하고 Buy_Amount로 2차 정렬을 한다.

Select Client_Name, Address, Buy_Amount

From Customer

Where Client_Num <= 7000

Order by Address, Buy_Amount;

7.3.4 INSERT 문

INSERT문은 테이블에 새로운 레코드를 추가하기 위해 사용되는 Query문이다.

형식>

INSERT INTO	[테이블 명]

(필드 리스트)

VALUES(필드값 리스트);

테이블명에는  데이터를 삽입하고자 하는 테이블 명이 들어간다. 그리고 필드 리스트는 Table의 필드 리스트를 말하는데, Values절에서 입력할 데이터들이 나열순서를 지정한다. 만일 필드 리스트가 생략될 경우 Values절은 반드시 Table에서 필드들이 정의된 순서대로 필드값을 나열해야 한다. 따라서 필드 리스트에서 나열 순서를 지정해 주는 것이 Query문장을 분석하는데 도움이 된다.

예1>

가령 Employee라는 테이블에 새로운 레코드를 추가하려 한다고 하자. Employee테이블에는 EmpNO, LastName, FirstName, PhoneNum, HireDate, Salary 라는 필드들을 가지고 있다. 여기서 EmpNo가 80, LastName이 Mark, FirstName이 Karl, PhoneNum가 500-8080, 그리고 Salary가 2000$이라는 새로운 레코드를 추가하려면 다음과 같은 SQL문을 사용한다. (단, HireDate는 정확한 데이터가 없어 입력할 수 없다고 가정한다.)

Insert into Employee

( EmpNo, LastName, FirstName, PhoneNum, Salary )

Values( 80033, "Mark", "Karl", "500-8080", 2000 );

7.3.5 Delete 문

DELETE문은 테이블에서 레코드를 삭제하기 위해 사용한다.

형식>

DELETE FROM [테이블 명]

WHERE [조건];

예1>

Employee 테이블에서 EmpNo가 80001인 직원정보를 삭제하라.

Delete From Employ

Where EmpNO = '80001';

7.3.6 UPDATE 문

UPDATE문은 테이블이 가지고 있는 레코드들을 갱신하기 위해 사용된다.

형식>

UPDATE	[테이블 명]

SET	[갱신 내용]

WHERE	[갱신 조건]

예>

만일 어떤 회사에서 연봉 10000$이하인 직원들의 임금을 1000$씩 올려준다고 하자 이때 직원 테이블은 Empolyee이고 임금 필드명은 Salary라고 할 때 Query문은 다음과 같다.

Update   Employee

Set	Salary = Salary + 1000

Where   Salary < 10000;

7.3.7 집합 함수

1) 종류

- SUM : 추출된 레코드들에서 선택된 필드 값들을 합산한다.

- AVG : 추출된 레코드들에서 선택된 필드 값들의 평균을 구한다.

- MIN : 추출된 레코드들에서 선택된 필드의 가장 작은 값을 구한다.

- MAX : 추출된 레코드들에서 선택된 필드의 가장 큰 값을 구한다.

- COUNT : 추출된 레코드들의 총 수를 구한다.

- GROUP BY : 검색한 데이터들을 특정 단위로 묶는다.

- HAVING : GROUP BY로 만들어진 그룹들 가운데 특정 조건을 만족하는 그룹만을 선택한다.

2) SUM

검색한 레코드들에서 지정한 필드들의 총합을 구한다.

형식>

Sum( 필드명 );

예>

어떤 회사가 직원들에게 지급하는 총 입금액을 구한다고 하자. 직원 테이블이 Employee, 임금 필드가 Salary라고 하면 Query문은 다음과 같다.

Select Sum( Salary )

From Employ;

3) AVG

검색한 레코드들에서 지정한 필드의 평균을 구한다.

형식>

AVG( 필드명 );

예>

어떤 회사의 아프리카 지사에 근무하는 직원들에게 지급하는 평균 임금액을 구해 보자. 직원 테이블이 Employee, 임금 필드가 Salary, 지사명 Region라고 하면 Query문은 다음과 같다.

Select AVG( Salary )

From Employee

Where Region = 'africa';

4) MIN & MAX

검색된 데이터들 중 지정된 필드의 가장 큰 값 또는 가장 작은 값을 구한다.

형식>

MIN( 필드명 )

MAX( 필드명 )

예>

어떤 백화점의 회원 고객 데이터베이스에서 구입액이 가장 많은 고객의 이름과 구입액을 구하고 가장 구입액이 적은 고객의 이름과 구입 액수를 구하는 Query는 다음과 같다.(고객 테이블=Customer, 구입액=Buy_Amount, 고객이름=Client_Name 이라고 하자.)

Select Client_Name, Max(Buy_Amount)

From Customer;

Select Client_Name, Min(Buy_Amount)

From Customer;

5) GROUP BY & HAVING

GROUP BY는 검색된 결과를 특정 필드를 기준으로 그룹화 할 수 있다. 그리고 HAVING은 GROUP BY로 그룹화 할 때 조건을 지정할 수 있다.

형식>

GROUP BY (필드명)

예1>

어떤 은행에서 각 지점별로 예탁금이 가장 많은 고객들의 데이터가 필요하다고 가정하자. 이때 고객의 예탁금 테이블이 Account, 고객이름은 Client, 예탁금은 Amount, 국가명은 Country ,지점명은 Region이라고 할 때 Query는 다음과 같다.

Select Client, Max(Amount), Region, Country

From Account

Group by Region;

예2>

예1>에서 미국에 있는 지점만 한정할 때 경우 Query는 다음과 같다.

Select Client. Max(Amount), Region

From Account

Group by Reigon

Having Country = 'US";

6) Count

검색된 레코드의 총수 또는 그룹 내 레코드 총수를 구할 수 있다.

형식>

Count( * )

예>

어떤 은행에서 각 지점별로 고객의 총수를 알고 싶다고 하자. 이때 고객의 예탁금 테이블이 Account, 지점명은 Region이라고 할 때 Query는 다음과 같다.

PHP 프로그래밍

PHP 프로그래밍

Select Region, Count(*)

From Account

Group by Region;

7.4 DDL (Data Definition Language)

7.4.1 DDL이란

데이터베이스에 새로운 테이블을 추가하거나, 테이블에 색인(index) 혹은 필드 등을 추가, 변경하는 등, 데이터 정의부분과 관련된 언어

7.4.2 CREATE 문

CREATE TABLE

데이터 베이스에 새로운 테이블을 추가한다.

형식>

CREATE TABLE [테이블명]

(

Field명  FieldType,

....

[PRIMARY KEY( Field명.. )

);

예>

8. MySQL 사용법

8.1 MySQL설치

MySQL에서 한글 캐릭터 셋으로 정렬을 하기 위해서는 소스 컴파일을 해야 한다. 바이너리 배포판은 Latin1으로 설정되어 있어 있기 때문에 한글로 정렬이 제대로 되지 않는다. 검색이 되지 않는 것은 아니다

먼저, gcc 컴파일러의 버전을 확인한다. cc 2.7.x 이전 버전은 버그가 있기 때문에 MySQL을 설치하기 위해서는 반드시 2.8.x버전 이상으로 업그레이드를 해야한다

1) 인터넷에서 Source 받아오기

http://www.mysql.org에서 최신 버전의 소스를 받아온다. 다운 받은 소스는 /tmp 밑이나 자신의 계정 밑에 저장한다.

2) 압축풀기

# zcat mysql-version.tar.gz | tar xvf -

( # gzip -d mysql-version.tar.gz

# tar xvf mysql-version.tar )

mysql-3.22.23b/

mysql-3.22.23b/Makefile.in

mysql-3.22.23b/README

mysql-3.22.23b/stamp-h.in

mysql-3.22.23b/Makefile.am

...

...

...

mysql-3.22.23b/support-files/mysql.spec.sh

mysql-3.22.23b/support-files/my-example.cnf.sh

mysql-3.22.23b/support-files/mysql-log-rotate.sh

mysql-3.22.23b/support-files/mysql.server.sh

mysql-3.22.23b/support-files/binary-configure.sh

주의) 만일 sun solaris를 사용하는 사용자는 sun tar 프로그램에 버그가 있기 때문에 압축을 풀기 전에 gnu tar를 다운 받아서 설치해야한다. 하지만 linux사용자라면 전혀 문제가 없기 때문에 걱정 안 해도 된다.

3) configure 스크립트 실행

압축이 풀린 디렉토리로 이동한 후 configure를 실행시킨다. 사용 가능한 옵션을 자세히 보려면 --help 를 붙여주면 된다.

# cd mysql-3.22.23

# ./configure --help

Usage: configure [options] [host]

Options: [defaults in brackets after descriptions]

Configuration:

--cache-file=FILE       cache test results in FILE

--help                  print this message

--no-create             do not create output files

--quiet, --silent       do not print `checking...' messages

--version               print the version of autoconf that created configure

...

다른 옵션은 모두 디폴트값을 쓰고 --prefix=PREFIX 와  --with-charset =CHARSET 두가지 만 설정을 하겠다.

--prefix :

컴파일이 끝난 후 파일들이 인스톨되는 디렉토리를 정해준다.

--with-charset :

정렬에 사용될 캐릭터 셋을 정해 준다. 한글정렬을 위해 지정이 필요하다. 기본적으로 정해진 값은 latin1 이며 한글정렬을 위해서는 □euc_kr'을 지정하면되다, 그 외에도 아래와 같은 캐릭터 셋을 지정할 수 있다.

use specified charset (default is latin1, must be one of: big5 danish cp1251 cp1257 croat czech dec8 dos euc_kr german1 hebrew hp8 hungarian koi8_ru koi8_ukr latin1 latin2 swe7 usa7 win1251 win1251_ukr ujis sjis tis620)

그럼, prefix에 /usr/local/mysql을 캐릭터 셋에 euc_kr을 주고 configure를 실행 시켜보자.

#./configure --prefix=/usr/local/mysql  --with-charset=euc_kr

loading cache ./config.cache

checking host system type... i586-pc-linux-gnu

checking target system type... i586-pc-linux-gnu

checking build system type... i586-pc-linux-gnu

checking for a BSD compatible install... (cached)

...

MySQL has a Web site at http://www.tcx.se/ which carries details on the

latest release, upcoming features, and other information to make your

work or play with MySQL more productive. There you can also find

information about mailing lists for MySQL discussion.

Remember to check the platform specific part in the reference manual for

hints about installing on your platfrom. See the Docs directory.

Thank you for choosing MySQL!

4) 컴파일 하기

이제 컴파일 하기 전 준비는 끝났다. 이제 간단히 make 명령을 이용해서 컴파일을 시작하면 된다.

# make

make  all-recursive

make[1]: Entering directory `/tmp/mysql-3.22.23b'

Making all in Docs

make[2]: Entering directory `/tmp/mysql-3.22.23b/Docs'

make[2]: Nothing to be done for `all'.

...

...

컴파일 시간은 AMD K6-2 350MHz, 64M RAM을 가진 PC에서 5분 20초 정도 걸린다고 하는데 실제로 해보면 조금 더 걸리는 것 같다. 만일 컴파일 중에 문제가 발생하면 INSTALL-SOURCE 파일을 참고한다. 여러 가지 상황별로 문제 해결 방법이 자세히 설명되어 있다.

5) 인스톨 하기

컴파일까지 무사히 끝냈다면 거의 설치한 것이나 다름없다. 이제 마지막으로 make install로 컴파일된 파일들을 인스톨하기만 하면 된다.

# make install

Making install in Docs

make[1]: Entering directory `/tmp/mysql-3.22.23b/Docs'

make[2]: Entering directory `/tmp/mysql-3.22.23b/Docs'

make[2]: Nothing to be done for `install-exec-am'.

/bin/sh ../mkinstalldirs /usr/local/mysql/info

mkdir /usr/local/mysql

...

make[2]: Leaving directory `/tmp/mysql-3.22.23b'

make[1]: Leaving directory `/tmp/mysql-3.22.23b'

6) 권한 테이블 초기화

지금까지의 작업으로 MySQL의 설치는 끝났다. 이제 MySQL을 사용하기 위한 준비작업만 하면 된다. 이 작업은 □mysql_install_db'라는 스크립트 프로그램만 실행 시켜주면 OK!

'mysql_install_db' 프로그램은  MySQL 데이터베이스 프로그램의 각종 권한을 관리하는 데이터 베이스인 mysql에 권한설정 관련 테이블을 생성하는 역할을 한다.

먼저, 인스톨이 완료된 MySQL 디렉토리로 이동한다

# cd /usr/local/mysql

그리고 mysql_install_db를 실행 시킨다.

#/usr/local/mysql/bin/mysql_install_db

Creating db table

Creating host table

Creating user table

Creating func table

Creating tables_priv table

Creating columns_priv table

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 !

This is done with:

/usr/local/mysql/bin/mysqladmin -u root password 'new-password'

See the manual for more instructions.

Please report any problems with the /usr/local/mysql/bin/mysqlbug script!

The latest information about MySQL is available on the web at http://www.mysql.com

Support MySQL by buying support/licenses at http://www.tcx.se/license.htmy.

데이터 파일의 위치는 /usr/local/var이며 데이터베이스는 디렉토리로 테이블은 파일로 존재한다. 참고로 바이너리 인스톨 시에는 데이터 디렉토리는  /usr/local/mysql/data 이다.

7) MySQL 데이터 베이스 프로그램 시작하기

드디어 MySQL을 시작을 한다. 시작하는 방법은 /usr/local/mysql/bin밑에 있는 □safe_mysqld'을 실행시키면 된다.

#/usr/local/mysql/bin/safe_mysqld --language=korean &

위에서 □&□은 mysql 데몬을 백그라운드 모드로 실행시킨다는 뜻이고 language=korean은 에러 메시지 같은 것을 한글로 볼 수 있게 해주다.

MySQL 프로그램이 제대로 작동하는지 확인한다.

# ps -ef | grep mysql

root     24879   634  0 23:33 pts/1    00:00:00 sh ./bin/safe_mysqld

root     24891 24879  0 23:33 pts/1    00:00:00 /usr/local/mysql/libexec/mysqld

root     24893 24891  0 23:33 pts/1    00:00:00 /usr/local/mysql/libexec/mysqld

root     24894 24893  0 23:33 pts/1    00:00:00 /usr/local/mysql/libexec/mysqld

root     24909   634  0 23:41 pts/1    00:00:00 grep mysql

위와 같이 데몬이 떠 있으면 정상이다.

8) root 패스워드 변경하기

권한 테이블들이 만들어졌고 MySQL 데몬이 실행되고 있다면, 먼저 MySQL root 유저의 패스워드를 변경해야 한다. MySQL의 root유저는 시스템의 root와는 전혀 상관 없이 MySQL의 기동, 권한관리, 데이터베이스 사용자 등록등의 작업을 하는 MySQL의 관리자이다.

MySQL root 암호 변경방법

/usr/local/mysql/bin/mysqladmin -u root password 'root-password'

예)

#/usr/local/mysql/bin/mysqladmin -u root password '1234'

9) 테스트

MySQL이 정상적으로 동작하는지 몇 가지 테스트 해본다. 우선 mysql 이라는 클라이언트 프로그램을 이용해 권한관리 데이터베이스인 mysql에 접속해 보자

사용법 : ./bin/mysql [OPTIONS] [database]

더 많은 옵션을 알고 싶으면 ./bin/mysql --help 라고 입력하면 된다.

[root@localhost mysql]# ./bin/mysql mysql

ERROR 1045: 'root@localhost' 사용자는 접근이 거부 되었습니다. (Using password: 아니오)

접속이 거부되었다는 에러가 발생한다. 왜냐하면 이미 MySQL 관리자의 패스워드를 변경했기 때문에 아래와 같이 암호를 이용해야 한다.

# ./bin/mysql -u root -p mysql

Enter password:

p옵션은 로그인시 패스워드를 사용한다는 뜻이다.

로그인이 성공하면 다음 메시지가 나타난다.

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.

Your MySQL connection id is 5 to server version: 3.22.23b

Type 'help' for help.

mysql>

이제 MySQL에 대한 몇가지 테스트를 해보자.

'status□ 명령은 MySQL에 대한 기본정보를 보여준다.

mysql> status

--------------

./bin/mysql  Ver 9.32 Distrib 3.22.23b, for pc-linux-gnu (i586)

Connection id:          6

Current database:       mysql

Current user:           root@localhost

Server version          3.22.23b

Protocol version        10

Connection              Localhost via UNIX socket

UNIX socket             /tmp/mysql.sock

Uptime:                 8 min 43 sec

Threads: 1  Questions: 37  Slow queries: 0  Opens: 10  Flush tables: 1  Open tables: 6

mysql> select pi()*4/10 ;

+------------+

| pi()*4/10  |

+------------+

| 1.25663706 |

+------------+

1 row in set (0.00 sec)

mysql> select 'Hello World? I\'m MySQL' AS string1 ;

+------------------------+

| string1                |

+------------------------+

| Hello World? I'm MySQL |

+------------------------+

1 row in set (0.00 sec)

현재 시간 표시

mysql> select now() ;

+---------------------+

| now()               |

+---------------------+

| 1999-07-16 00:05:42 |

+---------------------+

1 row in set (0.00 sec)

다음은 □mysql'이라는 데이터베이스를 사용한다는 뜻.

mysql> use mysql

Database changed

다음은 □user'라는 테이블의 내용을 보여준다.

mysql> desc user ;

+-----------------+---------------+------+-----+---------+-------+

| Field           | Type          | Null | Key | Default | Extra |

+-----------------+---------------+------+-----+---------+-------+

| Host            | char(60)      |      | PRI |         |       |

| User            | char(16)      |      | PRI |         |       |

| Password        | char(16)      |      |     |         |       |

| Select_priv     | enum('N','Y') |      |     | N       |       |

| Insert_priv     | enum('N','Y') |      |     | N       |       |

| Update_priv     | enum('N','Y') |      |     | N       |       |

| Delete_priv     | enum('N','Y') |      |     | N       |       |

| Create_priv     | enum('N','Y') |      |     | N       |       |

| Drop_priv       | enum('N','Y') |      |     | N       |       |

| Reload_priv     | enum('N','Y') |      |     | N       |       |

| Shutdown_priv   | enum('N','Y') |      |     | N       |       |

| Process_priv    | enum('N','Y') |      |     | N       |       |

| File_priv       | enum('N','Y') |      |     | N       |       |

| Grant_priv      | enum('N','Y') |      |     | N       |       |

| References_priv | enum('N','Y') |      |     | N       |       |

| Index_priv      | enum('N','Y') |      |     | N       |       |

| Alter_priv      | enum('N','Y') |      |     | N       |       |

+-----------------+---------------+------+-----+---------+-------+

17 rows in set (0.00 sec)

빠져나가기

mysql> \q

Bye

10) MySQL 서버 중지

MySQL서버의 동작을 중지시키기 위해서는 다음의 명령을 사용한다.

# ./bin/mysqladmin -p shutdown

Enter password:

$ mysqld daemon ended

[1]+  Done                    ./bin/safe_mysqld --language=korean

8.2 사용자 등록 및 권한설정

MySQL은 기본적으로 mysql 이라는 데이터 베이스내에 있는 3개의 테이블(user, db ,host)로 사용자 권한을 설정한다. 설치후에는 기본적으로 root 유저만 등록 되어 있다. 다른 사용자는 user 와 db 테이블에 등록을 해주어야 한다.

MySQL에서 사용자 권한은 크게 두가지로 나눠진다.

- MySQL서버에 접속할 수 있는 권한(user 테이블 사용)

- 각 데이터 베이스를 사용할 수 있는 권한(db 테이블 사용)

한가지 주의 할 점은 user 테이블에 권한을 'Y'로 주면 그 권한이 모든 데이타베이스에 적용이 된다는 점이다. 심지어 사용자 접근권한을 설정하는 mysql DB까지도 적용이 된다. 따라서 user 테이블에는 반드시 접속만 가능하도록 모든 기능을 'N' 로 주시고 db 테이블에서 사용자에게 적당한 DB를 주는 것이 바람직하다.

다음과 같은 내용으로 간단하게 myuser라는 사용자를 MySQL에 추가시켜 보자.

먼저, root로 로그인을 한 다음 myuser라는 사용자를 추가하고 MyDB라는 데이터 베이스를 생성한 다음 myuser에게 MyDB의 모든 접근권한을 부여한다.

root 패스워드 지정하기

먼저, root 사용자로 MySQL에 로그인을 한다.

[root@home /root]# mysql -u root -p mysql

Enter Password:

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 1961 to server version: 3.22.20a-log

Type 'help' for help.

mysql>

'myuser'라는 사용자를 등록한다.

mysql> insert into user values ( 'localhost', 'myuser', password('mypasswd'), 'N', 'N', 'N', 'N', 'N' ,'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N' );

Query OK, 1 row affected (0.00 sec)

values절의 값들은 테이블에 정의된 Field들의 순서와 반드시 일치 해야한다.

사용자가 사용할 DB와 권한을 줍니다.

mysql> insert into db values ( 'localhost', 'MYUSER', 'myuser', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y');

Query OK, 1 row affected (0.00 sec)

또는,

mysql> grant all on MYUSER.* to myuser;

Query OK, 1 row affected (0.00 sec)

빠져나가기

mysql> quit

Bye

권한 테이블을 다시 읽도록 서버를 Reload 합니다

[root@home /root]# /usr/local/mysql/bin/mysqladmin -u root -p reload

Enter Password:

8.3 테이블 만들기 및 활용

8.3.1 데이터베이스 만들고 선택하기

먼저 관리자(root)로 로그인 한다.

mysql> CREATE DATABASE zoo;

리눅스에서 데이터베이스 이름은 대소문자를 구분한다(단, SQL 키워드는 그렇지 않다). 따라서 데이터베이스 이름을  항상 'zoo'로  해야지  Zoo, zOO 등과 같이하면 안 된다. 테이블 이름도 마찬가지로 대소문자를 구분한다.

이제는 데이터 베이스를 만들었으니 MySQL에 □zoo'라는 데이터 베이스를 사용한다고 'use zoo'를 통해 알려주고 본격적으로 작업에 들어가자.(항상 데이터 베이스에 대한 작업을 할 경우 'use' 명령어로 알려 줘야 한다.)

mysql> USE menagerie

Database changed

데이터베이스는 한번만 만들면 되지만 사용할 때마다 use 문을 이용하여 사용할

데이터 베이스를 선택해야 한다. 다른 방법으로는 mysql을 시작할 때 데이터 베이스 이름을 써 주어도 된다

shell> mysql -h host -u user -p zoo

Enter password: ********

여기서 zoo는 패스워드가 아니다. 패스워드를 쓰려면 공백 없이 바로 -p 뒤에 붙여 써 주어야 한다(하지만 이 방법은 보안상 바람직한 방법이 절대 아니다. 패스워드가 글자그대로 화면에 보이기 때문이다. 누가 어깨 너머로 보고있다면 어떻게 할 것인가? 패스워드가 글자그대로 화면에 써진다는 것은 정말 위험하다. 현명한 관리자 및 사용자라면 -p 뒤에 패스워드를 적어 주는 "짓"은 하지 않을 것이다.) □zoo'는 패스워드가 아니라 사용할 데이터베이스이름이다.

8.3.2 테이블 만들기

데이터베이스를 만들고 난 후 'show tables'라는 명령을 이용해서 데이터 베이스에 들어 있는 테이블 리스트를 본다.

mysql> show tables;

Empty set (0.00 sec)

데이터베이스에 테이블을 만들지 않았기 때문에 당연히 아무 것도 없다.

정말로 중요하고 어렵게 느껴지는 것은 데이터베이스를 어떻게 설계할 것 인가이다. 어떤 테이블이 필요하고 이 안에 무슨 자료들을 넣어야 할지를 생각해야 한다. 여기서의 예에서는 각 애완 동물마다 한 개의 레코드를 두어야 할  것이다. pet 테이블이라고 이름 짓자. 각 테이블에는  애완 동물의 이름, 소유주(식구 이름이 될 것이다) 종, 성(암컷인지 수컷인지) 등등의 정보를 입력하고 싶을 것이다. 나이는? 나이도 필요할 것 같지만 시간에 따라  변하는 것이 나이이므로 나이에 대한 정보를 자주 갱신해 주어야 할 것이다. 보다 나은 방법을 강구해야 한다. 이런 상황을 미리 염두에 두고 설계해야 한다는 것이 데이터베이스 설계시 겪는  어려움이 아닐까 생각한다. 나이는 시간에 따라 변하므로 출생일을 기록해두고 현재 날짜와의 차이로부터 계산하면 좋을 것이다. MySQL은 몇 가지 산술 루틴을 제공하므로 이것은 어려운 일이 아니다. 나이대신 출생일을 기록해 두는 것은 다음 두가지 잇점이 있다:

● 다가오는 애완 동물의 생일을 미리 알려주는 일에 사용할 수 있다(동물에게

생일이라... 비현실적인 것 같지만, 이것은 다른 관점에서 생각해 볼 수 있다.

여러분의 고객의 생일은 어떤가? 언제 생일 축하카드를 보내야 하는 지 알 필요가 있지 않은가?).

● 오늘 날짜 말고 다른 날짜를 기준으로도 나이를 계산할 수 있다. 예를 들어

사망일을 기록해 놓으면 애완 동물의 수명을 알 수 있을 것이다.

애완 동물에 대한 정보로서 다른 것들도 생각할 수 있겠지만 이 정도로 해 두자.

충분하다.

CREATE TABLE 문으로 테이블에 둘 자료 구조를 명시할 수 있다:

mysql> CREATE TABLE pet (

->name VARCHAR(20),

->owner VARCHAR(20),

->species VARCHAR(20),

->sex CHAR(2),

->birth DATE,

->death DATE );

CREATE TABLE 다음에 테이블 이름을 써 주고 괄호 안에 열의 이름과 그 열의 자료형을 한 쌍으로 Field들을 쉼표로 구분하여 열거해 주면 된다. name, owner,  species, sex, birth등이 Field의 이름이며, VARCHAR(20), CHAR(2), DATE가 자료형이다. 자료형이란 말 그대로 자료의 형태이다. 자료는 문자열일 수 있고, 날짜 일 수 있고, 수 일수 있다.

어떻게 자료를 입력하느냐에 따라 다르겠지만 진돗개 "용감이"의 경우 다음처럼 될 수 있다.

name  owner  species   sex   birth     death

----------------------------------------------

용감이  홍길동   개     수컷  1998-3-4  NULL

VARCHAR는 길이가 변하는 문자열에 사용한다. 이름, 소유주, 종은  길이가 고정적이지 않은 문자열을 그 자료형으로 할 때 적당할  것이다. VARCHAR 형의 열들에 대해, 길이는 반드시 모두 같은 필요도 없고 20으로 고정될 필요도 없다.  1에서 255사이의 길이를 가질 수 있다. 적당하게 잡아 주면 된다(나중에 ALTER TABLE 문으로 조정할 수도 있다).  테이블을 만들었으니 데이터베이스 내 테이블 목록에 추가되었는가 확인하자.

mysql> SHOW TABLES;

+--------------------+

|Tables in menagerie |

+--------------------+

| pet                |

+--------------------+

테이블이 명시한대로 만들었는지 확인하기 위해서는 DESCRIBE 문을 사용한다:

mysql> DESCRIBE pet;

+---------+-------------+-----+-----+---------+------+

| Field   | Type        | Null| Key | Default |Extra |

+---------+-------------+-----+-----+---------+------+

| name    | varchar(20) | YES |     | NULL    |      |

+---------+-------------+-----+-----+---------+------+

| owner   | varchar(20) | YES |     | NULL    |      |

+---------+-------------+-----+-----+---------+------+

| species | varchar(20) | YES |     | NULL    |      |

+---------+-------------+-----+-----+---------+------+

| sex     | char(2)     | YES |     | NULL    |      |

+---------+-------------+-----+-----+---------+------+

| birth   |  date       | YES |     | NULL    |      |

+---------+-------------+-----+-----+---------+------+

| death   |  date       | YES |     | NULL    |      |

+---------+-------------+-----+-----+---------+------+

Field 부분과 Type 부분을 보고 Field의 이름과 자료형을 확인하자. describe는

언제든지 사용할 수 있다. 테이블 내에  Field의 이름 및 자료형이 많을 때 사용하면 유용하다.

8.3.3 테이블에 자료 넣기

테이블을 만든 후에는 테이블에 자료를 넣어야 한다. LOAD DATA 혹은 insert 문을 사용하면 된다.

애완 동물 자료가 다음과 같다고 가정하자(MySQL은 YYYY-MM-DD 형식의 날짜 포맷을 요구한다).

name     owner    species      sex     birth     death

-------------------------------------------------------------

Fluffy    Harold     cat         f   1993-02-04

Claws     Gwen       cat         m   1994-03-17

Buffy     Harold     dog         f   1989-05-13

Fang      Benny      dog         m   1990-08-27

Bowser    Dianne     dog         m   1998-08-31  1995-07-29

Chirpy    Gwen       bird        f   1998-09-11

Whistler  Gwen       bird            1997-12-09

Slim      Benny      snake       m   1996-04-29

입력해야 할 데이터가 많을 경우, 각 동물에 대한 자료를 미리 파일로 만들고 파일을 읽어드려서 테이블을 채우면 편리할 것이다.

pet.txt라는 파일에 다음과 같이 한 줄에 하나의 레코드씩 기록하면 된다.

# cat pet.txt

Fluffy  Harold    cat      f       1993-02-04

...

...

Field의 값들은 탭키나 스페이스로 구분하며 'CREATE TABLE' 문에 명시한 순서대로 각 Field의 값들을 열거해야 한다. 생략해도 되는 값(위에서 죽은 날짜와 성)에 대해서는 NULL값을 사용할 수 있다. 텍스트 파일에서 NULL값을 나타내기 위해서는 \N 이라고 써주면 된다. 예를  들어 Whistler의 예는 다음과 같을 것이다.

Whistler Gwen bird \N 1997-12-09 \N

pet.txt 파일을 로드하기 위해서는 다음처럼 LOAD DATA  문을 사용한다

mysql> LOAD DATA LOCAL INFILE "pet.txt" INTO TABLE pet;

<사용형식>

LOAD DATA LOCAL INFILE "파일이름" INTO TABLE 테이블이름;

한번에 한 개의 레코드를 추가하고자 할 때가 있을 것이다. CREATE TABLE 문을 사용하였을 때 열거한 순서대로 각 열의 값을 적어 주면 된다. 물론 Field의 자료형과 일치하는 값이어야 한다.

mysql> insert into pet

-> values( 'Puffball', 'Diane', 'hamster', 'f', '1999-03-30', NULL );

문자열 및 날짜는 반드시 작은 따옴표 ' 로 감싸 주어야 한다. 위에서 언급한 NULL값도 입력할 수 있다. (\N이라고 적으면 안된다).

8.3.4 테이블로부터 정보 검색

테이블에서 데이터를 검색하려면 SELECT문을 사용하면 된다.

<형식>

SELECT [Field 리스트] FROM [테이블 리스트] WHERE [검색조건];

[Field리스트] :

보고자 하는 Field들을 □,□로 구분하여 나열한다.

[테이블] :

검색하고 하는 테이블들을 나열한다.

[검색 조건] :

검색을 원하는 조건을 나열한다.

테이블 안에 모든 데이터 검색

가장 간단한 SELECT 문의 형태로 다음 같이 사용하면 된다.

mysql> SELECT * FROM pet;

+----------+--------+---------+------+------------+------------+

| name     | owner  | species | sex  | birth      | death      |

+----------+--------+---------+------+------------+------------+

| Fluffy   | Harold | cat     | f    | 1993-02-04 | NULL       |

| Claws    | Gwen   | cat     | m    | 1994-03-17 | NULL       |

| Buffy    | Harold | dog     | f    | 1989-05-13 | NULL       |

| Fang     | Benny  | dog     | m    | 1990-08-27 | NULL       |

| Bowser   | Diane  | dog     | m    | 1998-08-31 | 1995-07-29 |

| Chirpy   | Gwen   | bird    | f    | 1998-09-11 | NULL       |

| Whistler | Gwen   | bird    | NULL | 1997-12-09 | NULL       |

| Slim     | Benny  | snake   | m    | 1996-04-29 | NULL       |

| Puffball | Diane  | hamster | f    | 1999-03-30 | NULL       |

+----------+--------+---------+------+------------+------------+

이런 식으로 SELECT문을 사용하는 것은 테이블의 전체 정보를 보고자 할 때 유용하다. 방금 막 초기 데이터 뭉치를 올렸을 때 제대로 올려졌는지 확인코자 사용할 수 있다. 사람 사는 일이 그렇듯, 방금 본 결과에는 잘못된  것이 있다: Bower의 출생일자가 사망일자보다 늦다. 죽은 뒤에 태어났다?! 확인해 보니 birth는 1989-08-31이 되어야 함을 알 수 있었다고 하면 이를 어떻게 고칠까?

다음과 같이 질의를 던져주면 된다.

mysql> UPDATE pet SET birth='1989-08-31' WHERE name='Bowser';

주어진 조건에 맞는 데이터만 검색.

여러분은 테이블에서 특별한 행들만 뽑아낼 수 있다. 예를 들어 Bower의 생일이

정말로 바뀌었는 가 확인하기 위해 Bower의 레코드만 뽑아낼 수 있다:

mysql> SELECT * FROM pet WHERE name = "Bower";

+--------+-------+---------+------+------------+-----------+

| name   | owner | species | sex  | birth      | death     |

+--------+-------+---------+------+------------+-----------+

| Bowser | Diane  | dog    | m    |1989-08-31  |1995-07-29 |

+--------+-------+---------+------+------------+-----------+

birth Field의 값이 1998년도가 아닌 1989년으로 올바르게 수정됨을 확인할 수 있다. 문자열 비교는 대소문자를 무시하는 비교다. 따라서 "bowser", "BOWSER" 등은 같은 문자열을 의미한다(위에서는 "Bowser"를 사용했다)

어떤 Field에 대해서도 조건을 명시해 줄 수가  있다. 예를 들어 1998년 이후에 태어난 동물을 알고 싶다면 birth 열을 대상으로 검사하면 된다.

mysql> SELECT * FROM pet WHERE birth >= "1998-1-1"

+----------+-------+---------+------+-----------+------+

| name     | owner | species | sex  | birth     |death |

+----------+-------+---------+------+-----------+------+

| Chirp y  | Gwen  | bird    |   f  |1998-09-11 | NULL |

| Puffball | Diane | hamster |   f  |1999-03-30 | NULL |

+----------+-------+---------+------+-----------+------+

조건을 조합할 수 도 있다:

mysql> SELECT * FROM pet WHERE species = "dog" AND sex = "f";

+-------+--------+---------+------+------------+-------+

| name  | owner  | species | sex  | birth      | death |

+-------+--------+---------+------+------------+-------+

| Buffy | Harold | dog     | f    |1989-05-13  | NULL  |

+-------+--------+---------+------+------------+-------+

위의 예는 개이면서 수컷인 동물을 검색하는 것이다.

위에서는  AND를 사용하였지만 OR를 사용할 수도 있다.

mysql> SELECT * FROM pet WHERE species = "snake" OR species = "bird";

+----------+-------+---------+------+-----------+-------+

| name     | owner | species | sex  | birth     | death |

+----------+-------+---------+------+-----------+-------+

| Chirpy   | Gwen  | bird    | f    |1998-09-11 | NULL  |

| Whistler | Gwen  | bird    |NULL  |1997-12-09 | NULL  |

| Slim     | Benny | snake   | m    |1996-04-29 | NULL  |

+----------+-------+---------+------+-----------+-------+

AND와 OR를 섞어서 사용할 수 있다. 이렇게 할 때는 그룹지어지는 조건들을 괄호로 묶는 것이 좋다:

mysql> SELECT * FROM pet WHERE (species = "cat" AND sex = "m")

-> OR (species = "dog" AND sex = "f");

+-------+--------+---------+------+------------+-------+

| name  | owner  | species | sex  | birth      | death |

+-------+--------+---------+------+------------+-------+

| Claws | Gwen   | cat     | m    | 1994-03-17 | NULL  |

| Buffy | Harold | dog     | f    | 1989-05-13 | NULL  |

+-------+--------+---------+------+------------+-------+

8.3.5 특정한 Field 선택

테이블에서 한 행 전체를 보기보다는 관심 있는 Field들만 보고 싶다면 보고자 하는 Field 이름을 다음처럼 사용하면 된다.(아래 예는 name, birth열을 보고 싶은 경우이다)

mysql> SELECT name, birth FROM pet;

+----------+------------+

| name     |   birth    |

+----------+------------+

| Fluffy   | 1993-02-04 |

| Claws    | 1994-03-17 |

| Buffy    | 1989-05-13 |

| Fang     | 1990-08-27 |

| Bowser   | 1989-08-31 |

| Chirpy   | 1998-09-11 |

| Whistler | 1997-12-09 |

| Slim     | 1996-04-29 |

| Puffball | 1999-03-30 |

+----------+------------+

소유주만 보고자 할 때:

mysql> SELECT owner FROM pet;

+--------+

| owner  |

+--------+

| Harold |

| Gwen   |

| Harold |

| Benny  |

| Diane  |

| Gwen   |

| Gwen   |

| Benny  |

| Diane  |

+--------+

하지만 중복된 행이 있다. distinct 중복된 행을 없애 보자.

mysql> SELECT distinct owner FROM pet;

+--------+

| owner  |

+--------+

| Benny  |

| Diane  |

| Gwen   |

| Harold |

+--------+

distinct 키워드를 사용하면 된다.

WHERE 절을 이용하여 행의 선택과 Field의 선택을 조합할 수 있다. 예를 들어 개와 고양이에 대해서만 이름, 종, 생일을 알고자 할 때 다음처럼 SELECT문을 사용할 수 있다.

mysql> SELECT name, species, birth FROM pet

-> WHERE species = "dog" OR species = "cat";

+--------+---------+------------+

| name   | species |   birth    |

+--------+---------+------------+

| Fluffy | cat     |1993-02-04  |

| Claws  | cat     |1994-03-17  |

| Buffy  | dog     |1989-05-13  |

| Fang   | dog     |1990-08-27  |

| Bowser | dog     |1989-08-31  |

+--------+---------+------------+

8.3.6 행 정열하기

지금까지 보인 예에서 결과가 전혀 정렬되어 있지 않았음을 알 수 있을 것이다.

결과가 정렬된다면 원하는 자료를 훨씬 쉽게 알아 볼 수 있다. 정렬하기 위해서는 ORDER BY 절을 사용하면 된다. 아래는 생일을 기준으로 정렬한 것이다.

mysql> SELECT name, birth FROM pet ORDER BY birth;

+----------+------------+

| name     |  birth     |

+----------+------------+

| Buffy    | 1989-05-13 |

| Bowser   | 1989-08-31 |

| Fang     | 1990-08-27 |

| Fluffy   | 1993-02-04 |

| Claws    | 1994-03-17 |

| Slim     | 1996-04-29 |

| Whistler | 1997-12-09 |

| Chirpy   | 1998-09-11 |

| Puffball | 1999-03-30 |

+----------+------------+

역순으로 정렬하려면 desc 키워드를 열 이름 뒤에 적어준다.

mysql> SELECT name, birth FROM pet ORDER BY birth desc;

+----------+------------+

| name     | birth      |

+----------+------------+

| Puffball | 1999-03-30 |

| Chirpy   | 1998-09-11 |

| Whistler | 1997-12-09 |

| Slim     | 1996-04-29 |

| Claws    | 1994-03-17 |

| Fluffy   | 1993-02-04 |

| Fang     | 1990-08-27 |

| Bowser   | 1989-08-31 |

| Buffy    | 1989-05-13 |

+----------+------------+

하나의 열에 대해서만이 아니라 여러 열에 대해서도 정렬할 수 있다. 예를 들어

먼저 동물 이름으로 정렬하고 각 동물에 대해 생일로 정렬하되 가장 어린 것(가장 늦게 태어난 것; 역순 정렬)이 먼저 오게 하려면 다음처럼 한다.

mysql> SELECT name, species, birth FROM pet

->     ORDER BY species, birth DESC;

+----------+---------+-----------+

| name     | species | birth     |

+----------+---------+-----------+

| Chirpy   | bird    |1998-09-11 |

| Whistler | bird    |1997-12-09 |

| Claws    | cat     |1994-03-17 |

| Fluffy   | cat     |1993-02-04 |

| Fang     | dog     |1990-08-27 |

| Bowser   | dog     |1989-08-31 |

| Buffy    | dog     |1989-05-13 |

| Puffball | hamster |1999-03-30 |

| Slim     | snake   |1996-04-29 |

+----------+---------+-----------+

DESC 키워드는 바로 그 앞에 열 이름(birth)에만 적용된다는 것을 주의하라. species는 여전히 오름차순으로 정렬된다.

8.3.7 날짜 계산

MySQL은 날짜를 다루는 몇 가지 함수를 제공해 준다.

애완 동물의 나이가 얼마나 되는지 계산하려면 오늘 날짜와 출생 날짜를 구하고, 두 날짜를 일수로 환산한 후, 그 차를 연간 일수 즉 365일로 나누어주면 될 것이다.

mysql> SELECT name, (to_days(now())-to_days(birth))/365 FROM pet;

+----------+-------------------------------------------+

| name     | (TO_DAYS(NOW())-TO_DAYS(birth))/365       |

+----------+-------------------------------------------+

| Fluffy   |                                      6.15 |

| Claws    |                                      5.04 |

| Buffy    |                                      9.88 |

| Fang     |                                      8.59 |

| Bowser   |                                      9.58 |

| Chirpy   |                                      0.55 |

| Whistler |                                      1.30 |

| Slim     |                                      2.92 |

| Puffball |                                      0.00 |

+----------+-------------------------------------------+

여기서 두 가지 사항을 개선해 보자. 결과가 이름 혹은 나이순으로  정렬되었으면 좋겠고, 나이에 해당하는 라벨 명을 표현식 그대로 쓰는 것보다는 "age"같은 것으로 하는 것이 좋을 것이다.

mysql> SELECT name, (to_days(now())-to_days(birth))/365 as age

->  FROM pet ORDER BY name;

나이순으로 정렬하려면 ORDER BY name 대신 ORDER BY age로 써 주면 된다.

사망시 나이도 비슷한 방법으로 알아 낼 수 있다.

mysql> SELECT name, (to_days(death)-to_days(birth))/365 as age

-> FROM pet WHERE death is not null ORDER BY age;

now()대신 death를 사용하면 된다. 여기서 아직 죽지 않은 동물의 수명을 조사한다는 것은 무의미하기 때문에 death 필드가 null이 아닌 경우를 조건으로 해 주었음을 주의하자. 조심할 것은 death is not null처럼 조건을 주어야 한다. death != null 처럼 주어서는 안된다. null값에 비교 연산자를 적용할 수 없다. 나중에 이 문제는 다시 다룰 것이다.

다음 달에 생일인 동물을 알려면 어떻게 해야 할까? 이러한 문제를 위해 MySQL은 날짜에서 연도나, 달을 계산하는 함수를 제공한다: year(), month, day().month() 예를 통해 알아 보자.

mysql> SELECT name, birth, month(birth) FROM pet;

+----------+------------+--------------+

| name     | birth      | MONTH(birth) |

+----------+------------+--------------+

| Fluffy   | 1993-02-04 |            2 |

| Claws    | 1994-03-17 |            3 |

| Buffy    | 1989-05-13 |            5 |

| Fang     | 1990-08-27 |            8 |

| Bowser   | 1989-08-31 |            8 |

| Chirpy   | 1998-09-11 |            9 |

| Whistler | 1997-12-09 |           12 |

| Slim     | 1996-04-29 |            4 |

| Puffball | 1999-03-30 |            3 |

+----------+------------+--------------+

month는 달에 해당하는 수를  반환해 주며, 물론 그  범위는 1에서 12까지이다.

다음달을 나태내기 위해서는 1을 더한 달을 명시해주면 된다.

mysql> SELECT name, birth FROM pet WHERE month(birth) = 10;

그런데 문제가 있다. 12월인 경우  13을 명시해 주어야 하나?  13월이란 없다.

현재 달이 몇 월이든지 상관없도록 새로운 조건식을 생각해 내야 한다. 여기에

두 가지를 소개한다:

● month(date_add(now(), interval 1 month));

now()는 현재 날짜 및 시간을 반환해 준다. 여기에 1달이라는 기간을 더 해주고

달로 바꾸면 해결된다.

● mod(month(now()), 12) + 1;

mod는 어떤 수를 다른 수로 나눈 나머지 값을 반환하는 함수이다. 첫 번째  인자를 두 번째 인자로 나눈 결과를 반환한다. 여기서는 현재  달 month(now())를 12로 나눈 뒤 다음 달을 나타내기 위해 1을 더해 준다. 이번  달이 12월이라면 12로 나눈 나머지가 0이므로 여기에 1을 더해 다음달 1월을 나태내 줄 수 있다.

완전한 SQL문은 각각 다음과 같다.

<방법1>

mysql> SELECT name, birth FROM pet

->  WHERE   MONTH(birth)  =  MONTH(DATE_ADD(NOW(),   INTERVAL  1 MONTH));

<방법1>

mysql> SELECT name, birth FROM pet

-> WHERE MONTH(birth) = MOD(MONTH(NOW()),12) + 1;

8.3.8 null 값에 대해

NULL값은 특별한 값이다. 개념적으로 NULL이 의미하는 바는 "아직 정해지지 않은 불확정 값"을 의미한다. 이것은  다른 값들과는 다르게 취급된다. NULL에는 산술 비교 연산을 수행할 수 없다.

어떤 값과 NULL값을 =, <, !=을 이용하여 비교하는 것은 의미가 없다. 불확정 값을 어떻게 확정된 값과 비교할 수 있을 것인가? 다음을 보라.

mysql> SELECT 1 = NULL, 1 != NULL, 1 < NULL, 1 > NULL;

+----------+-----------+----------+----------+

|1 = NULL  |1 != NULL  |1 < NULL  | 1 > NULL |

+----------+-----------+----------+----------+

|     NULL |     NULL  |     NULL |    NULL  |

+----------+-----------+----------+----------+

위에서 보듯 확정되지 않은 값과 확정된 값의  비교는 불확정한 값이 된다. 의미가 없다. 다음과 같이 하면 의미가 있다:

mysql> SELECT 1 IS NULL, 1 IS NOT NULL;

+-----------+---------------+

| 1 IS NULL | 1 IS NOT NULL |

+-----------+---------------+

|        0  |             1 |

+-----------+---------------+

MySQL에서 거짓 값은 0으로 참값은 1로 나타낸다.

8.3.9 패턴 일치

패턴 일치 기능은 매우 유용한 기능이다. 보다 빠르고 정교하게 원하는 조건을

명세하여 검색할 수 있게 해주는 기능이기 때문이다.

MySQL은 표준 SQL 패턴뿐만 아니라 유닉스에서 사용하는 정규 표현식에 해당하는 패턴 일치 기능도 지원한다.

SQL에서 □_□은 임의 한 문자를 의미하며, □%□는 임의의 수의 문자(0개의 문자를 포함)를 가르킨다. SQL 패턴은 대소문자를 비교하지 않는다. LIKE 이후에 패턴을 준다는 것을 기억하자.

b로 시작하는 이름에 대해서 검색할 때:

mysql> SELECT * FROM pet WHERE name LIKE "b%";

+--------+--------+---------+------+------------+------------+

| name   | owner  | species | sex  | birth      | death      |

+--------+--------+---------+------+------------+------------+

| Buffy  | Harold | dog     | f    | 1989-05-13 | NULL       |

| Bowser | Diane  | dog     | m    | 1989-08-31 | 1995-07-29 |

+--------+--------+---------+------+------------+------------+

□fy□로 끝나는 이름에 대해서 검색할 때:

mysql> SELECT * FROM pet WHERE name LIKE "%fy";

+--------+--------+---------+------+------------+-------+

| name   | owner  | species | sex  | birth      | death |

+--------+--------+---------+------+------------+-------+

| Fluffy | Harold | cat     | f    | 1993-02-04 | NULL  |

| Buffy  | Harold | dog     | f    | 1989-05-13 | NULL  |

+--------+--------+---------+------+------------+-------+

w를 포함하는 이름을 검색할 때:

mysql> SELECT * FROM pet WHERE name LIKE "%w%";

+----------+-------+---------+------+------------+------------+

| name     | owner | species | sex  | birth      | death      |

+----------+-------+---------+------+------------+------------+

| Claws    | Gwen  | cat     | m    | 1994-03-17 | NULL       |

| Bowser   | Diane | dog     | m    | 1989-08-31 | 1995-07-29 |

| Whistler | Gwen  | bird    | NULL | 1997-12-09 | NULL       |

+----------+-------+---------+------+------------+------------+

정확하게 5개의 글자로 이루어진 이름에 대해서 검색할 때는 다음과 같이 밑줄을 5개 적어준다.

mysql> SELECT * FROM pet WHERE name LIKE "_____";

+-------+--------+---------+------+------------+-------+

| name  | owner  | species | sex  | birth      | death |

+-------+--------+---------+------+------------+-------+

| Claws | Gwen   | cat     | m    | 1994-03-17 | NULL  |

| Buffy | Harold | dog     | f    | 1989-05-13 | NULL  |

+-------+--------+---------+------+------------+-------+

이젠 정규표현에 기준을 둔 패턴일치에 대해 알아보자.

정규표현식 문자	설 명
.	문자 하나
*	앞에 나온 문자의 0개 이상의 반복
^	문자열 처음
$	문자열 끝
[,]	괄호안의 문자들에 일치
{,}	반복을 나타낼 때. 예로 n번 반복할 때 {n}으로 적는다.

여기서 SQL 패턴은 전체 값과 일치해야 "일치한다"고 하지만 정규표현은 값의 어느 부분과 일치해도 "일치한다"고 단정한다는 것을 유의해야 한다. 예를 들어,

SELECT * FROM pet WHERE name REGEXP "ffy";

와

SELECT * FROM pet WHERE name LIKE "ffy";

는 전혀 다른 결과를 낳는다.

문자 a나 b나 c중 하나를  가르키는 표현은 [abc]이다. 범위를  주어서 표현할 수도 있다. 정규표현은 대소문자를 구별한다. 따라서 대문자던 소문자던 상관없이 알파벳  문자 하나를 가르키는 표현은 [a-zA-Z]로 해야 한다.

*는 0개 이상의 문자들이라고 했다. x* 는 x, xx, xxx ... 에 해당한다. [0-9]*는 7,

12, 345, 678등의 임의의 길이를 갖는 수를 나타낸다. ^abc는 줄 처음에 abc로 시작하는 패턴을 abc$는 abc로 끝나는 문자열을 의미한다. 정규 표현식을 쓸 때는 LIKE대신 REGEXP을 사용한다.

이름이 소문자 b 혹은 대문자 B로 시작하는 조건으로 검색

mysql> SELECT * FROM pet WHERE name REGEXP "^[bB]";

+--------+--------+---------+------+------------+------------+

| name   | owner  | species | sex  | birth      | death      |

+--------+--------+---------+------+------------+------------+

| Buffy  | Harold | dog     | f    | 1989-05-13 | NULL       |

| Bowser | Diane  | dog     | m    | 1989-08-31 | 1995-07-29 |

+--------+--------+---------+------+------------+------------+

이름이 fy로 끝날 때($를 사용한다):

mysql> SELECT * FROM pet WHERE name REGEXP "fy$";

+--------+--------+---------+------+-----------+-------+

| name   | owner  | species | sex  | birth     | death |

+--------+--------+---------+------+-----------+-------+

| Fluffy | Harold | cat     | f    |1993-02-04 | NULL  |

| Buffy  | Harold | dog     | f    |1989-05-13 | NULL  |

+--------+--------+---------+------+-----------+-------+

정확하게 5개의 문자로 이름어진 값은 다음 정규 표현에 일치한다:

^.....$

이것은 반복 연산자를 이용하여 다음처럼 쓸 수도 있다.

^.{5}$

8.3.10 행수 세기

누가 어떤 애완 동물을 몇이나 소유했는지 어떻게 알아낼 수 있을까?

이에 대한 답으로 count()함수를 사용하면 되며 적당하게 조건을 부여해 주면 된다.

mysql> SELECT COUNT(*) FROM pet;

+----------+

| COUNT(*) |

+----------+

|        9 |

+----------+

각 소유주가 소유한 애완동물의 수는 다음 처럼 하면 확인 할 수 있다:

mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner;

+--------+----------+

| owner  | COUNT(*) |

+--------+----------+

| Benny  |       2  |

| Diane  |       2  |

| Gwen   |       3  |

| Harold |       2  |

+--------+----------+

각 owner의 모든 레코드들을 한데 묶기 위해 GROUP BY 절을 사용한 것을  주목하라. 이렇게 하지 않으면 에러 메시지를 보게 될 것이다.

mysql> SELECT owner, COUNT(owner) FROM pet;

ERROR 1140 at line 1: Mixing of GROUP columns (MIN(),MAX(),COUNT()...)

with no GROUP columns is illegal if there is no GROUP BY clause

COUNT()와 GROUP BY는 데이터에 여러 모양으로 특성을  부여하는 데 쓸모가 있다.

다음 예제들도 참고하자:

각 종에 해당하는 동물의 수:

mysql> SELECT species, COUNT(*) FROM pet GROUP BY species;

+---------+----------+

| species | COUNT(*) |

+---------+----------+

| bird    |        2 |

| cat     |        2 |

| dog     |        3 |

| hamster |        1 |

| snake   |        1 |

+---------+----------+

성에 따른 동물의 수:

mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex;

+------+----------+

| sex  | COUNT(*) |

+------+----------+

| NULL |        1 |

| f    |        4 |

| m    |        4 |

+------+----------+

NULL은 "값을 모름"의 의미이다.

종과 성에 따른 동물의 수:

mysql> SELECT species, sex, COUNT(*) FROM pet GROUP BY species, sex;

+---------+------+----------+

| species | sex  |COUNT(*)  |

+---------+------+----------+

| bird    | NULL |       1  |

| bird    | f    |       1  |

| cat     | f    |       1  |

| cat     | m    |       1  |

| dog     | f    |       1  |

| dog     | m    |       2  |

| hamster | f    |       1  |

| snake   | m    |       1  |

+---------+------+----------+

바로 위의 경우와는 달리, 특정한 동물에  대해서만 조사해 볼 수 도 있다. 개와

고양이의 경우에만 각 성에 대해 몇 마리인지 조사해 보자:

mysql> SELECT species, sex, COUNT(*) FROM pet

-> WHERE species = "dog" OR species = "cat"

-> GROUP BY species, sex;

+---------+------+----------+

| species | sex  | COUNT(*) |

+---------+------+----------+

| cat     | f    |        1 |

| cat     | m    |        1 |

| dog     | f    |        1 |

| dog     | m    |        2 |

+---------+------+----------+

8.3.11 테이블 여러 개 사용하기

pet 테이블은 애완 동물에 대한 정보를 갖고 있다. 수의사에 치료받으러 갔던 횟수나 새끼를 나은 날짜 같은 사건들에 대한 다른 정보를 기록하고싶다면 별도의 테이블이 필요할 것이다. 테이블은 다음과 같은 조건을 요구할 것이다:

● 해당 동물의 이름을 갖고 있어야  한다. 어떤 애완 동물에게 일어난 사건인지

분별해야 하기 때문이다.

● 언제 일어난 일인지 알기 위해 날짜 정보가 필요하다.

● 어떤 사건인지 묘사해 둘 필요가 있다.

● 사건을 분류하려면 사건 유형을 나타내는 필드도 있으면 좋을 것이다.

이와 같은 조건을 생각하여, 다음처럼 테이블을 만들어 보자:

mysql> CREATE TABLE event (name VARCHAR(20), date DATE,

-> type VARCHAR(15), remark VARCHAR(255));

pet 테이블의 경우처럼 파일로부터 데이터를 테이블로 올리자. event.txt에

다음처럼 적혀 있다고 하자.

Fluffy	1995-05-15	litter	4 kittens, 3 female, 1 male

Buffy	1993-06-23	litter	5 puppies, 2 female, 3 male

Buffy	1994-06-19	litter	3 puppies, 3 female

Chirpy	1999-03-21	vet	needed beak straightened

Slim	1997-08-03	vet	broken rib

Bowser	1991-10-12	kennel

Fang	1991-10-12	kennel

Fang	1998-08-28	birthday	Gave him a new chew toy

Claws	1998-03-17	birthday	Gave him a new flea collar

Whistler	1998-12-09	birthday	First birthday

다음 처럼 테이블을 채우자:

mysql> LOAD DATA LOCAL INFILE "event.txt" INTO TABLE event;

지금까지 pet 테이블을 다루면서 배웠듯이  event 테이블에 대해 여러  가지 질의를 해 볼 수 있을 것이다. 하지만 정보가 불충분할 때는 어떻게 하는가?

새끼를 낳았을 때 어미의 나이를  알려면 어떻게 해야 하는가? event 테이블을 통해 언제 새끼를 낳았는지는 알 수 있지만 어미의 나이라든가, 소유주라든가 하는 것은 pet 테이블을 통해서 알아내야 한다. 따라서 SELECT 문을 사용할 때 두 개의 테이블이 필요하다.

mysql> SELECT pet.name, (TO_DAYS(date) - TO_DAYS(birth))/365 AS age,

-> remark FROM pet, event

-> WHERE pet.name = event.name AND type = "litter";

+--------+------+-----------------------------+

| name   | age  | remark                      |

+--------+------+-----------------------------+

| Fluffy | 2.27 | 4 kittens, 3 female, 1 male |

| Buffy  | 4.12 | 5 puppies, 2 female, 3 male |

| Buffy  | 5.10 | 3 puppies, 3 female         |

+--------+------+-----------------------------+

위의 예로부터 몇가지 알아 두어야 할 사항이 있다:

● FROM 절에 사용할 테이블을 모두 적어 주어야 한다. 이것들 모두로부터의

정보가 필요하기 때문이다.

● 여러 테이블에서 정보를 뽑아 합할 때는 한 테이블의 레코드가 다른 테이블의

레코드와 어떻게 일치하는 지 명시해 주어야 한다. 여기서는 두 테이블 모두 name 필드를 갖고 있으므로 이것을 이용하면 된다. 위에서 WHERE 절에 pet.name =  event.name 조건을 줌으로써 두 개의 테이블의 같은 동물에 해당하는 레코드에 대해서 질의를 하게 된다. 서로 다르다면 의미가 없다.

● 두 테이블 모두 name 필드를 갖고  있으므로 어느 테이블에 속하는 필드인지를 구분하기 위해 <테이블이름>.<필드이름>의 형식으로 적어 주었다. 즉 테이블 이름과 필드 이름을 점으로 구분하여 적어 준다.

위에서 테이블은 서로 달랐다. 하지만  동일한 테이블에 대해서 위에서처럼 사용할 필요가 있을 때가 있다. 예를 들어 개의 수컷과 암컷을 짝지어 주려면 어떻게 해야 하는가? 동일한 테이블에 대해서 성이 같은지 다른지 검사해야 한다. 다음 한 예를 든다.

mysql> SELECT p1.name, p1.sex, p2.name, p2.sex, p1.species

-> FROM pet AS p1, pet AS p2

-> WHERE p1.species = p2.species AND p1.sex = "f" AND p2.sex = "m";

+--------+------+--------+------+---------+

| name   | sex  | name   | sex  | species |

+--------+------+--------+------+---------+

| Fluffy | f    | Claws  | m    | cat     |

| Buffy  | f    | Fang   | m    | dog     |

| Buffy  | f    | Bowser | m    | dog     |

+--------+------+--------+------+---------+

8.3.12 배치 모드(일괄 처리 모드)로 사용하기

지금까지는 대화식으로 사용하였다. 질의를 쳐  넣고 결과를 보는 식의 반복적인

작업이었다. 작업 내용 전부를 파일에 기술해 준 후 한꺼번에 처리할 수도 있다. 이렇게 하는 작업을 배치 작업이라고 한다는 것쯤은 알아두자. 다음과 같은 식으로 사용한다.

shell> mysql < batch-file

작업 내용을 써 둔 파일 내용을 표준 입력으로 받으면 된다. 호스트명 및 사용자 명, 패스워드를 입력할 필요가 있으면 추가로 써 준다.

shell> mysql -h host -u user -p < batch-file

Enter password: ********

여러분이 배치 모드에서 사용할 파일을 작성하는 것은 바로 스크립트를 작성하는

것이다. 기본 결과는 대화식으로 할 때와는 다르다. SELECT DISTINCT species FROM  pet을 시켰을 때 대화식과 배치 모드에서의 결과를 보자. 내용은 같지만 형식이 다르다.

대화식:

+---------+

| species |

+---------+

| bird    |

| cat     |

| dog     |

| hamster |

| snake   |

+---------+

배치 모드:

species

bird

cat

dog

hamster

snake

배치 모드에서도 대화 모드에서와 같은 형식으로의 출력을 원하면 mysql 실행시-t 옵션을 주면 된다. 만약 실행되는 명령어도 출력에 포함하고 싶다면 -vvv를 붙여라. 그렇다면 무슨 유익이 있길래 배치 모드를 사용할까? 다음에 몇 가지 적어 두었다.

● 질의를 자주 한다면 스크립트로 만들어 두는 것이 실행할 때마다 매번 다시 쳐 넣어주는 수고를 없애 준다.

● 이미 작성한 스크립트를 수정하여 개선할 수 있고 새로운 스크립트를 작성할 수 있는 잇점이 있다.

● 여러 줄에 걸치는 매우 복잡한 질의를 수행할 때는 배치 모드가 적당할  것이다. 실수를 했을 때 대화모드라면 전부 다시 쳐 넣어 주어야 한다. 배치 모드일때는 파일만  수정해 주면 된다. 하지만 MySQL은 readline 라이브러리(히스토리  기능을 구현한 라이브러리)기능을 사용하므로 대화 모드일 때도 다시 명령어를 쳐 넣는 수고를 크게 덜 수 있다.

● 출력 결과가 굉장히 많다면 배치모드로 실행시키고 페이지(일정한 페이지 줄수로 문서를 보여주는 프로그램을 통칭하는 명칭)를 통해 보면 좋을 것이다.

shell> mysqlk < batch-file | less

● 출력 결과를 다른 파일로 저장할 수 있다. 저장된 파일은 추가 작업의

출발점으로 활용될 수 있다.

shell> mysql < batch-file > mysql.out

● 작성한 스크립트를 다른 사람과 공유할 수 있다. 다른 사람도 여러분이 작성한 스크립트를 실행할 수 있으며 참고할 수 있다.

● 어떤 작업은 성격상 배치모드에서만 실행할 수 있다. 일정한 시간 간격으로 어떤 작업을 할 때는 cron을 이용하여 배치모드에서 처리할 수 밖에 없다.

9. MySQL과 PHP3 연동

1. MySQL과 PHP3 연동 과정

2. mailling Table 만들기

mail Table 만드는 query

create table mail (

id int(11) DEFAULT '0' NOT NULL auto_increment,

email varchar(35),

primary key(id) );

3. 메일링 리스트 구현하는 php3 프로그램 소스

maildb.php3

<?php

$admin_id = "1234";

$admin_mail = "webmaster@hostname";

/////////////////////////////////////////////////////////////

// Mysql DB 접속하기 위해서는DB 이름(USER_DB), 사용자 ID(user_id), 그리고 비밀 번//호(password)가 있어야 한다. 이것들이 없다면 DB 접속을 할 수 없다.

////////////////////////////////////////////////////////////

$connect = mysql_connect( "localhost", "testuser", "test*" ) || die( "Mysql  server에 접속할 수 없습니다.□ );

mysql_select_db( "USER_DB", $connect );

//////////////////////////////////////////////////////////////

// 에러 페이지와 작업 완료 페이지를 만드는 function입니다. write($a, $b); 식으로 촐출하//며 $a에는 $head가 $b에는 $mesg가 대응된다.

//////////////////////////////////////////////////////////////

function write( $head, $mesg ){

header( □Content-Type: text/html" );

echo  "<html><head></head>

<body bgcolor=ffffff><center>

<h1>$head</h1>

<h2>$mesg</h2>

<hr size=1>http://yCHAT.pe.kr

</center>

</body></html>";

exit;

}

// write function 끝

// 메일 주소를 DB에 등록하는 부분이다. 먼저 메일 주소가 정상저으로 입력 되었는지 확//인하고 비 정상이면 write function을 이용하여 에러 페이지를 생성하고 정상이면 DB에 등//록한다.

if( $mail_action == "reg" ) {

if(!$email){

$head = "메일 주소 에러입니다□;

$mesg = "e-mail 주소를 입력하ㅔ요□;

write( $head, $mesg );

}

if( !ereg("@", $email) ){

$head = "메일주소 에러□;

$mesg = "e-mail 주소를 올바르게 입력하세요.□;

write( $head, $mesg );

}

// 중복 등록을 검사하는 부분

// mail 테이블에서 email 필드에 대한 질의를 하여, 그 결과로 $current_row 변수를 생성합니다.

$quel = "select email from mail where email='$email'";

$result = mysql_query( $quel, $connect );

$current_row = mysql_fetch_row( $result );

// 입력한 email과 같은 current_row가 있으면 에러를 보여 이미 등록되었음을 알립니다.

if( $current_row[0] == $email ){

$head = "이미 등록됨□;

$mesg = "귀하의 메일은 이미 등록되었습니다.□;

$write( $head, $mesg );

}

// 중복되지 않은 데이터를 DB에 등록하느 부분입니다. insert 명령으로 mail 테이블에 id와 //email을 추합니다. id는 자동 증가요소이므로 □□으로 표시합니다.

$email = addslashes( $email );

$quel = " insert into mail values( '', '$email' ) ";

$result = mysql_query( $quel, $connect );

$head = "등록 성공□;

$mesg = "귀하의 메일주소가 성공적으로 등록되었습니다.□;

write( $head, $mesg );

}

if( $mail_action = admin ){

header( "Content-Type: text/html" );

echo "<html><head><title>관리자</title></head>

<body bgcolor=ffffff><center><h1>관리자 페이지</h1>

<h3>관리자 ID를 기록하세요!</h3>

<form method=post action=$PHP_SELF>

<input type=hidden name=mail_action value=logon>

<table>

<tr>

<td><input type=password name=uid size=20></td>

<td><input type=submit value='입장□></td>

</form></tr>

</table>

<hr><font size=-1><a href=http://domainname>httpd:domainname </a>	</font> </center>

</body></html>";

exit;

}

// 관리자가 비밀번호를 입력하여 접속하면 다음에서 비밀번호를 확인하여 접속 허락여부를 결정한다.

elsief($mail_action == logon){

if( $uid == $admin_id ){

// 브라우저에 쿠키를 설정하는 부분입니다. 쿠키의 이름은 $login이고 여기에 $uid를 설정합니다. 쿠키 호출은 $login로 합니다.

// 여기에는 메일 발송 폼과 메일 주소정리 메뉴가 있습니다.

SetCookie( "logid", "$uid", "" );

header( "Centent-Type: text/html" );

echo "<html><head><title>관리자 메뉴</title></head>

<body bgcolor=ffffff>

<center><h1> 관리자 페이지</h1>

<font size=4>메일 발송하기</font><p>

<form method=post action=$PHP_SELF>

<input type=hidden name=mail_action value=send>

<table><tr><td>제목</td>

<td><input type=text name=subject size=30></td></tr>

<tr><td>내용></td><td><textarea cols=50 rows=10 name=comments>	</textarea></td></tr>

<tr>

<td colspan=2 align=center><input type=submit value='메일발송□></td>

</form></tr></table>

<hr width=50%>

<a href=$PHP_SELF?mail_action=mlist>메일 주소정리</a>

<hr size=1><a href=http://domainname>http://domainname.pe.kr></a>

</center></body>

</html>";

exit;

}

else{

// 비밀번호가 관리자와 다르면 보여주는 페이지

$head = "관리자가 아닙니다□;

$mesg = "관리자만이 사용할 수 있습니다□;

write( $head, $mesg );

}

}

// 메일을 발송하는 부분입니다. mail 테이블을 읽어서 차례로 정리하고, $row[id], $row[email] 이라는 요소로 불러들여 mail 명령을 이용하여 메일을 발송합니다.

elsief( $mail_action == send ){

$quel = "select id, email from mail order by id DESC";

$j = 0;

$result = mysql_query( $quel, $connect );

$total = mysql_affect_rows() -1;

for( $i=0 ; $i<=total ; $i++ ){

mysql_data_seek( $result, $i );

$row = mysql_fetch_array( $result );

mail( "$row[email]", "$subject", $comments,

"from: $admin_mail\nReply-To: $admin_mail" );

$j++;

}

$head = "메일 발송 완료□;

$mesg = "$j 개의 메일 발소을 완료하였습니다□;

write( $head, $mesg );

}

// DB에 저장된 E-mail 주소를 삭제하기도하고 목록을 화면에 보여주는 페이지입니다.

elsief( $mail_action = "mlist" ) {

if( $logid == $admin_id ){

if( $modify == "erase" ) {

$quel = "delete from mail where id=$num";

$result = mysql_query( $query, $connect );

}

header( "Content-Type: text/html" );

echo "<html><head><title>관리자 페이지</title></head> <body bgcolor=ffffff><center><h1>등록 메일 리스트</h1>

<table border><tr><th>순서</th></th>E-mail 주소</th> <th> 주소관리</th>

</tr>";

$quel = "select id, email from mail order by id DESC";

$result = mysql_query( $quel, $connect );

$total = mysql_affected_rows() -1;

for( $i=0; $i <= $total ; $i++ ){

mysql_data_seek( $result, $i );

$row = mysql_fetch_array( $result );

echo "<tr><td>$row[id]</td>

<td>$row[email]</td><td><a href=$PHP_SELF?	mail_action=mlist&modify=erase&num=$row[id]삭제	</a></td></tr>";

}else{

$head = "관리자 에러□;

$mesg = "관리자 확인을 먼저하세요□;

write( $head, $mesg );

}

}

mysql_close( $connect );

?>