날짜: 1996-05-08 | 글쓴이: 도아 | 4902 번 | 프린트 | 메일로보내기

제 8강 - msqlperl의 사용법


데이터베이와 웹을 연동하기위해서는 dB 엔진 자체에서 제공하는 API를 사용하거나 API와 유사한 dB 어댑터를 사용해야한다.

Perl로 데이터베이스를 접속하기위한 많은 어댑터가 있으며, msqlperl은 Perl로 mSQL을 접속하기위한 어댑터이다. 기본적으로는 mSQL에서 지원하고있는 API 함수를 펄로 구현한 것이므로 API를 사용하는 것과 거의 동일한 방법으로 사용하면된다.

펄과 다른 데이터베이스와 연동을 위한 모듈은 다음 URL에서 구할 수 있으므로 참고하기 바란다.

http://www.hermetica.com/ msqlperl의 사용

msqlperl을 사용하기위해서는 msqlperl의 Method를 사용하기 전에 반드시 다음과 같은 문장을 수행해야 한다.

use Msql;

msqlperl의 매뉴얼에는 use Msql2;를 사용하도록 되어있지만 실제 설치는 Msql.pm으로 되므로 use Msql2;를 사용하면 제대로 동작하지 않는다. 따라서 반드시 use Msql;을 사용해야 한다.

이 문장은 다음 문장과 정확히 동일한 문장이다.

BEGIN {
	requrie 'Msql.pm';
	import Msql;
}

BEGIN은 다른 것들 보다 우선해서 처리하라는 펄의 키워드이다. 반대 개념으로 사용하는 END라는 키워드도 있다. 지원 명령어

# 데이터베이스 엔진에 접속
$dbh = Msql->connect; 			# 로칼 dB 엔진에 접속
$dbh = Msql->connect($host); 		# 원격 dB 엔진에 접속
$dbh = Msql->connect($host, $database);	# 윈격 dB 엔진에 접속한 후, 
					# 데이터베이스를 선택

# 데이터베이스의 선택
$dbh->selectdb($database); 		# 데이터베이스의 선택

# 데이터베이스의 목록과 테이블 목록
@arr = $dbh->listdbs; 			# 데이터베이스의 목록을 가져옴
@arr = $dbh->listtables; 		# 표의 목록을 가져옴
$error_message = $dbh->errmsg; 		# 질의 수행시 오류메시지를 가져옴

# 데이터베이스에 질의를 전송
$sth = $dbh->listfields($table); 	# 표의 스키마를 가져옴
$sth = $dbh->query($sql_statement); 	# SQL 문장을 dB엔진으로 전송

# 질의 결과를 가져옴
@arr = $sth->fetchrow; 		# 표의 한행을 가져옴
%hash = $sth->fetchhash; 	# 위와 동일하지만 연관배열로 가져옴
$sth->dataseek($row_number); 	# 행에대한 옵셋을 변경
$sth->as_string; 		# 질의 결과를 문자열로 가져옴

# 인덱스 처리
@indices = $sth->listindices; 			# mSQL 2.0에서만 사용 가능 
@arr = $dbh->listindex($table,$index); 		# mSQL 2.0에서만 사용 가능
($step,$value) = $dbh->getsequenceinfo($table) 	# mSQL 2.0에서만 사용 가능

# 메타데이타. 테이블 스키마 정보
$scalar = $sth->numrows; 	# 표의 줄수
$scalar = $sth->numfields; 	# 표의 필드수
@arr = $sth->table; 		# 각 필드의 데이블 명 
@arr = $sth->name; 		# 필드명 
@arr = $sth->type;		# 각 필드의 타입, msql.h에 정의되어 있으며, 
		   		# Msql::CHAR_TYPE, Msql::INT_TYPE, 
		   		# Msql::REAL_TYPE를 통해 접근가능하다. 
@arr = $sth->isnotnull; 	# Not null인지를 판정하는 부울값의 배열 
@arr = $sth->isprikey; 		# Primary Key인지를 판정하는 부울값의 배열 
@arr = $sth->length; 		# 바이트로 표현된 각 필드의 길이를 갖는 배열
설명

msqlperl은 mSQL에 포함되어 있는 C API와 가능한 비슷하게 설계되었다. msqlperl의 또다른 특징은 StudlyCaps를 사용한다는 것이다. StudlyCaps에대한 자세한 사항은 이절 뒷부분을 참고하기 바란다.

msqlperl은 내부적으로 Msql와 Msql::Statement의 두개의 크래스를 처리하고 있지만 두번째 형식은 거의 사용할 필요가 없다. 이것은 query나 listfield 문장에의해 리턴되는 스테이트먼트 핸들을 통해 자동적으로 이루어지때문이다. 따라서 사용자가 사용할 유일한 크래스는 Msql이다. 데이터베이스의 접속

msqlperl은 다음과 같은 세가지 형태의 데이타베이스 접속 명령을 제공한다.

$dbh = Msql->connect; 		# dB 서버와 웹 서버가 같은 호스트에 있는 경우 
$dbh = Msql->connect($host); 	# dB 서버와 웹 서버가 다른 호스트에 있는 경우 
$dbh = Msql->connect($host, $database); 	# 위와 동일하며, 
					 	# 접속시 데이타 베이스를 선택

이 명령을 이용해서 사용자는 원하는 호스트나 데이타 베이스에 접속할 수 있다.

첫번째 매개변수를 지정하지 않거나 널 문자열을 지정하는 경우, msqlperl은 UNIX 소켓(일반적으로 /dev/msql)을 통해 접속한다. 이 것은 TCP를 통해 접속하는 것보다 성능면에서 훨씬 우수하므로 dB 서버와 웹서버가 같은 호스트에 있는 경우에는 첫 번째 매개변수를 지정하지 않고 사용하는 것이 낫다.

두번째 매개변수로서 데이타베이스의 이름을 줄 수있으며, 이 매개변수로 접속 후 특정 데이타베이스를 선택할 수 있다.

접속에 성공한 경우에는 데이터베이스 핸들을 리턴하며 그렇지 못한 경우에는 데이터베이스 핸들은 정의되지 않는다.

따라서 데이터베이스를 접속한 후 다음과 같은 코드로 데이터베이스의 접속여부를 확인해야 한다.

$dbh = Msql->connect;
defined($dbh) || die '데이타베이스에 접속할 수 없습니다';

나중에 데이타 베이스에 접근하기위해서는 이 데이타베이스 핸들을 사용해야 한다. 데이타베이스 핸들

위에서 언급한 것처럼

$dbh = Msql->connect($host, $database);

로 데이타베이스 핸들을 얻을 수 있다. 이 데이타베이스 핸들로 접속된 소켓, 호스트, 데이타베이스를 알 수 있다.

$scalar = $dbh->sock; 
$scalar = $dbh->host; 
$scalar = $dbh->database;

단지 하나의 변수로 접속하거나, 변수없이 접속했다면, 호스트와 데이타베이스는 정의되지 않은 값을 리턴한다. 데이터베이스의 선택

$dbh->selectdb($database); # dB 선택. 반드시 connect 명령으로 dB 엔진에 먼저 
			   # 접속해야 함

만약 connect 명령을 사용할때 데이타베이스를 선택하지않았거나 이전에 connect 명령으로 얻은 데이타베이스 핸들을 사용해서 다른 데이타베이스를 접속하려면 selectdb를 사용한다. 데이터베이스의 목록과 테이블의 목록

@arr = $dbh->listdbs(); # dB의 목록을 배열로 리턴. 반드시 connect 명령을
			# 먼저 실행해야 한다. 
@arr = $dbh->listtables; # dB에 등록된 테이블의 목록을 리턴. 
			 # 반드시 connect 명령과 selectdb 명령을 
			 # 먼저 수행해야 한다.

위의 두 명령은 dB 엔진에 등록된 데이타베이스의 목록과 데이타베이스에 등록된 테이블의 목록을 배열로 리턴한다. 예1 - dB 목록과 테이블 목록 가져오기

다음은 msqlperl의 예로서 접속한 호스트와 선택된 데이터베이스를 출력하고, 데이터베이스의 목록과 선택된 데이터베이스에 등록된 테이블의 목록을 출력하는 예이다.

기능적으로는 명령행에서 사용하는 relshow와 유사한 프로그램으로 보면된다.

 1 : #!/usr/local/bin/perl
 2 : use Msql;
 3 : 
 4 : $dbh = Msql->connect;
 5 : defined($dbh) || die '데이타베이스에 접속할 수 없습니다';
 6 : $dbh->selectdb('commlab');
 7 : 
 8 : $sock = $dbh->sock;
 9 : $host = $dbh->host;
10 : $database = $dbh->database;
11 : 
12 : @db = $dbh->listdbs();
13 : @tables = $dbh->listtables();
14 : 
15 : print "접속한 호스트: $host\n";
16 : print "선택한 데이타베이스: $database\n";
17 : print "소켓: $sock\n\n";
18 : 
19 : print "다음은 등록된 데이타베이스의 목록입니다.\n";
20 : print '+' . '-' x 38 . "+\n";
21 : for(0..$#db) {
22 : 	print '|   ' . $db[$_] . ' ' x (40 - length($db[$_]) - 5) . "|\n"; 
23 : }
24 : print '+', '-' x 38, "+\n\n";
25 : 
26 : print "다음은 등록된 테이블의 목록입니다.\n";
27 : print '+' . '-' x 38 . "+\n";
28 : for(0..$#tables) {
29 : 	print '|   ' . $tables[$_] . ' ' x (40 - length($tables[$_]) - 5) 
		. "|\n"; 
30 : }
31 : print '+', '-' x 38, "+\n";

msqlperl을 사용하면서 주의할 것은 msqlperl을 이용해서 데이터베이스에 접속, 질의하기위해서는

#!/usr/local/bin/perl -w
use Msql;
$dbh = Msql->connect;
$dbh->selectdb('commlab');

와 같은 4개행이 꼭 필요하다는 것이다. 스테이트먼트 핸들

다음 두개의 메소드는 스테이트먼트 핸들을 리턴한다:

$sth = $dbh->listfields($table); 
$sth = $dbh->query($sql_statement);

$sth를 이용하면 API에의해 제공되는 모든 메타데이타를 알아낼 수 있다.

$scalar = $sth->numrows; 
$scalar = $sth->numfields; 
@arr = $sth->table; 		# 각 필드의 데이블 명 
@arr = $sth->name; 		# 필드명 
@arr = $sth->type;		# 각 필드의 타입, msql.h에 정의되어 있으며, 
		   		# Msql::CHAR_TYPE, Msql::INT_TYPE, 
		   		# Msql::REAL_TYPE를 통해 접근가능하다. 
@arr = $sth->isnotnull; 	# Not null인지를 판정하는 부울값의 배열 
@arr = $sth->isprikey; 		# Primary Key인지를 판정하는 부울값의 배열 
@arr = $sth->length; 		# 바이트로 표현된 각 필드의 길이를 갖는 배열

마지막 6개의 메소드는 배열을 리턴한다(perlref와 perlldsc를 보기바란다). 단지 한 필드의 이름만 필요한 경우 다음과 같은 스칼라 참조를 사용할 수 있다.

$name_of_third_column = $sth->name->[2]

@all_column_names = $sth->name; 
$name_of_third_column = $all_column_names[2];

와 동일한 문장이다. 예2 - 테이블 스키마 출력하기

 1 : #!/usr/local/bin/perl
 2 : @var_type = ('모름', '정수형', '문자형', '실수형', 'Ident', '널', 
 		'텍스트', '날자', '화폐', '시간');
 3 : 
 4 : use Msql;
 5 : $dbh = Msql->connect;
 6 : defined($dbh) || die '데이타베이스에 접속할 수 없습니다';
 7 : $dbh->selectdb('commlab');
 8 : 
 9 : @tables = $dbh->listtables();
10 : 
11 : foreach(@tables) {
12 : 	$sth = $dbh->listfields($_);
13 : 
14 : 	unless(defined($sth)) {
15 : 		print $dbh->errmsg(), "\n";
16 : 	}
17 : 
18 : 	@fields = $sth->name;
19 : 	@types = $sth->type;
20 : 	@notnull = $sth->isnotnull;
21 : 	@length = $sth->length;
22 : 
23 : 	print "테이블 이름: $_\n";
24 : 	for(0..$#fields) {
25 : 		print "필드명: $fields[$_]\n";
26 : 		print "필드형: $var_type[$types[$_]]\n" if($types[$_] <= 10);
27 : 		print "필드형: 시스템\n" if($types[$_] > 10);
28 : 		print "필요필드: $notnull[$_]\n";
29 : 		print "길이: $length[$_]\n\n";
30 : 	}
31 : }
SQL질의와 데이터 가져오기

$sth = $dbh->listfields($table); 	# 표의 스키마에대한 핸들을 리턴
$sth = $dbh->query($sql_statement); 	# 질의 결과에대한 핸들을 리턴

이들 두 명령은 mSQL 설명서에서 설명하고 있는 것과 유사하게 동작한다. 이들은 msql 서버가 사용자에게 전달하는 것이 무엇인지 알 수있도록 하는 스테이트먼트 핸들을 리턴한다. 오류가 발생한 경우, 스테이트먼트 핸들은 정의되지 않는다. 따라서 질의를 수행한 후에는 오류의 원인을 알아보기위해 다음과 같은 코드를 사용해야 한다.

unless(defined($sth)) {
    $msg = $dbh->errmsg;
    die "$msg";
}

listfields에의해 리턴된 값으로 테이블의 크기는 알 수 없다. 따라서 이 스테이트먼트 핸들에대한 numrow()는 "N/A"라는 문자열을 리턴하게 된다.

@arr = $sth->fetchrow; # 테이블에서 다음 행의 데이타 값을 배열로 리턴

서버로 부터 다음 행의 데이타 값의 배열을 리턴한다. 유사하게

%hash = $sth->fetchhash; # 테이블에서 다음 행의 데이타 값을 연관배열로 리턴

는 연관배열을 리턴한다. 해쉬에서 키는 테이블의 필드명이고, 값은 필드의 값이다. 테이블에 동일한 필드명을 갖는 필드가 있는 경우 둘 중 한 필드를 삭제해야만 이 메소드를 사용할 수 있다. 그렇지 않으면 fetchrow를 사용해야 한다.

$sth->dataseek($row_number); # 가져올 데이타의 옾셋을 변경

스테이트먼트 핸들에 연관된 데이타의 옾셋을 지정한다. 다음번 fetchrow는 dataseek에의해 지정된 행(첫행은 0)을 리턴할 것이다. 한번의 Query 수행으로 전체 테이블 표시하기

스테이트먼트 핸들의 전체 내용을 보는 손쉬운 방법은 as_string 메소드이다. 이 작업은 다음의 몇몇 예외사항을 제외하고는 msql 모니터와 유사하다.

  • 필드 폭은 해당 필드내 전체 엔트리를 조사함으로서 계산된다.
  • 제어문자는 역슬리쉬된 8진수로 사상된다.
  • 역슬래쉬는 두번 사용한다(\대신 \\)
  • 수치 값은 올바르게 조정된다(정수와 실수 둘다)

이러한 차이는 다음 표에의해 예시할 수 있다: msql로의 입력(실제 줄바꿈은 여기서는 ^M으로 대치되었다.)

CREATE TABLE demo ( 
first_field CHAR(10), 
second_field INT 
) \g 

INSERT INTO demo 
VALUES ('new line',2)\g 

INSERT INTO demo 
VALUES ('back\slash',1)\g 

INSERT INTO demo 
VALUES ('cr^Mcrnl nl',3)\g

msql의 출력
첫번째 필드 두번째 필드
new line 2
back\slash 1
crnlr nl 3
pmsql의 출력
첫번째 필드 두번째 필드
new\012line 2
back\\slash 1
cr\015crnl\012nl 3
예3 - 검색

다음은 특정 데이터베이스의 특정 테이블로부터 Digital이라는 단어를 포함한 행을 검색하는 예이다. 중간자 검색을 하기위해 like를 사용했으며, 모니터 프로그램인 msql의 출력과 동일한 결과를 얻기위해 as_string 메소드를 사용했다.

 1 : #!/usr/local/bin/perl
 2 : 
 3 : use Msql;
 4 : $dbh = Msql->connect;
 5 : defined($dbh) || die '데이타베이스에 접속할 수 없습니다';
 6 : $dbh->selectdb('commlab');
 7 : 
 8 : $sth = $dbh->query("select * from testbook where pub like '%Digital%'"); 
 9 : unless(defined($sth)) {
10 : 	$msg = $dbh->errmsg;
11 : 	die "$msg";
12 : }
13 : $string = $sth->as_string;
14 : print $string;
핸들의 종료

데이타베이스나 스태이트먼트 핸들을 갖는 스칼라 변수가 값을 갖지 않을 때 Msql은 적당한 동작(결과를 삭제(free)하거나 데이타베이스 접속을 종료한다)을 취한다. 따라서 결과를 삭제(free)하거나 접속을 닫고싶으면 다음 중 하나를 사용하면 된다.

  • 핸들의 정의를 삭제
  • 다른 목적으로 핸들을 사용
  • 핸들이 영역을 벗어나록 설정
  • 프로그램을 종료
오류메시지

Msql 크래스에서 오류메시지를 출력하는 안정적인 방법은 errmsg()로서 이것은 C API에서 제공하고있는 msqlErrMsg 변수의 현재값을 리턴한다. 또한 전역변수로 $Msql::db_errstr가 있으며, 이 변수는 항상 마지막 오류메시지를 갖는다. errmsg()가 다음에 수행될 메시지로 초기화되는 반면 $Msql::db_errstr는 그렇지 않다. -w 스위치

Msql를 사용할때 펄의 -w 스위치는 디버깅을 하는데 많은 도움이 된다. 만약 펄 프로그램을 -w 스위치로 호출한다면, errmsg()로 부터 경고를 얻을 수 있다. 이 것은 프로그램내에서 오류메시지를 처리하지 않고도 msql 서버로부터 오류메시지를 얻는 손쉬운 방법이다.

무엇이 어떻게 진행되는지 자세히 알고자 하는 경우, David의 설명서에있는 환경변수를 설정하면 된다. David의 디버깅을 위한 조언은 아주 뛰어난 것으로 덧붙일 것이 없다.

-w 스위치를 사용하면서 msql 서버로부터의 오류메시지를 보고싶지 않다면 $Msql::QUIET라는 변수에 참값을 할당하면 된다. NULL 필드

테이블 내의 NULL 필드는 정의되지 않은 값을 펄에 리턴한다. mSQL 2.0에서 새로운 점

API에서 query()함수는 query에의해 영향을 미치는 행의 수를 리턴한다. 리턴 코드가 0보다 큰 값이라면, 이것은 query가 정상적으로 수행된 것을 의미하며 query에의해 영향을 받은 행의 수를 알아낼 수 있다.(즉, SELECT에의해 리턴된 행의 수, UPDATE에의해 변경된 행의 수, DELETE에의해 삭제된 행의 수).

테이블에 연관된 모든 인덱스를 찾기위해 스테이트먼트 핸들에대한 listindices() 메소드를 호출할 수 있다. 인덱스에 사용된 필드를 찾기위해 데이타베이스 핸들에대한 listindex($table,$index) 메소드를 호출할 수 있다.

INT_TYPE, CHAR_TYPE, REAL_TYPE외에 mSQL 2에서는 몇몇 새로운 필드 형을 가지고 있으며 이 형에대한 접근은 IDENT_TYPE, NULL_TYPE, TEXT_TYPE, DATE_TYPE, UINT_TYPE, MONEY_TYPE, TIME_TYPE, IDX_TYPE, SYSVAR_TYPE을 이용하면 된다. 각각의 형에대한 값은 다음과 같다.

INT_TYPE	  1
CHAR_TYPE	  2
REAL_TYPE	  3
IDENT_TYPE	  4
NULL_TYPE	  5
TEXT_TYPE	  6
DATE_TYPE	  7
UINT_TYPE	  8
MONEY_TYPE	  9
TIME_TYPE	 10
IDX_TYPE	253
SYSVAR_TYPE	254
다른 포트로의 연결

mSQL API는 mSQL이 컴파일 될때 내정된 포트가 아닌 다른 포트로의 연결을 허용한다. 이러한 특징을 사용하기위해 MSQL_TCP_PORT라는 환경변수를 설정해야 한다. 사용자는 프로그램 내에서

$ENV{'MSQL_TCP_PORT'} = 1234; # 또는1112나 1113나 4333나 4334

라는 명령을 이용해서 환경변수를 설정할 수있다. 이 명령에 이어지는 connect()는 지정된 포트로 설정된다.

로컬 머신의 UNIX 소켓으로 connect()하기 위해서는 MSQL_UNIX_PORT를 사용한다. 버전 정보

MsqlPerl의 버전은 항상 펄 표준으로서 $Msql::VERSION에 저장된다.

mSQL API는 몇몇 내부 설정 변수에 접근하는 방법을 구현했다. 이들 설정 매개변수는 gethostinfo, getserverinfo과 getprotoinfo이다. 이들 세개 모두 크래스 메소드로서 데이타베이스 핸들을 통해 사용할 수 있다. 그러나 어떤 환경하에서는 데이타베이스 핸들과 무관할 수도 있다. 이들 세개는 현재 프로그램내에서 마지막 connect()명령을 반영하는 전역변수를 리턴한다. 이것은 connect()를 호출하기 전에는 빈 문자열이나 "0"을 리턴한다는 것을 의미한다. 데이타베이스 관리

관리자의 shutdown, createdb, dropdb, reloadacls은 데이타베이스 핸들을 통해 모두 접근 가능하며, msqladmin으로하는 것과 동일한 방법으로 구현되었다.

mSQL 엔진은 이러한 명령들이 데이타베이스 관리자가 아닌 다른 사용자에의해 호출되는 것을 허용하지 않는다. 따라서 이들중 하나를 사용할때에는 확실하게 리턴과 오류코드를 검사해야 한다. StudlyCaps

펄 프로그래머는 보통 ListTables를 입력하기 보다는 list_tables나 listtables로 입력하기를 좋아한다. mSQL API는 어디에서든 StudlyCaps를 사용하며, MsqlPerl의 이전 버전도 마찬가지 이다. $VERSION 1.06에서 부터 모든 메소드는 내부적으로 소문자 이지만 원하는 대로 쓸 수있다. 대소문자는 무시되며, 가독성을 개선하기위해 밑줄을 사용했다.

서로다른 메소드 명을 사용하는 대가는 무시할만하다. 알려진 이름으로 변환될 수 있는 임의의 메소드 명은 일단 프로그램 내에서 정의되고, 이 프로그램이 종료될때까지 별명을 유지할 것이다. 자유롭게 fetch_row나 connenT 또는 이전 프로그램처럼 ListDBs로 사용해도 된다. 물론 이러한 것들은 계속 동작한다.



다음글: 제 9강 - msqlperl - relshow 구현 (4805)1996-05-09
이전글: 제 7강 - mSQL - 시스템 변수 (5274)1996-05-07

세상사는 이야기

  • 장난(?)으로 시작한 여 >
  • 탈옥의 필수, QuickDo >
  • 윈도 10, 한영 전환도 >
  • 바보도 할 수 있는 War >
  • 북마크에도 확장 아이 >
  • 크롬은 가라, 비발디가 >
  • 감히 아이폰 관리의 최 >
  • 디지털 노마드의 편집 >
  • [블로그 복귀 알림] 새 >
  • 오타도 즐거운 안드로 >


  • RSS 구독 (익명 | 회원 | 강좌 | 포럼)
    (C) 1996 ~ 2014 QAOS.com All rights reserved.