# Example Makefile for ArcEngine C++ Programming on Linux
#
# The PROGRAM macro defines the name of the program or project. It
# allows the program name to be changed by editing in only one
# location
#
PROGRAM = basic_sample
#
# Command line parameters: Edit these parameters so that you can
# easily run the sample by typing "make -f Makefile.Linux run".
#
# You will need to:
# (1) Describe parameters here. ex: IN_SHAPEFILE is the input shapefile
# (2) Define parameters below this comment box.
# ex: IN_SHAPEFILE = /mycomp/data/shapefile.shp
# (3) Add the parameters to the run target at the end of this file
# ex: ./$(PROGRAM) $(IN_SHAPEFILE)
#
#
# The INCLUDEDIRS macro contains a list of include directories
# to pass to the compiler so it can find necessary header files.
#
# The LIBDIRS macro contains a list of library directories
# to pass to the linker so it can find necessary libraries.
#
# The LIBS macro contains a list of libraries that the the
# executable must be linked against.
#
INCLUDEDIRS = \
-I$(ARCENGINEHOME)/include \
-I/usr/X11R6/include
LIBDIRS = \
-L$(ARCENGINEHOME)/bin \
-L/usr/X11R6/lib
LIBS = -larcsdk
#
# The CXXSOURCES macro contains a list of source files.
#
# The CXXOBJECTS macro converts the CXXSOURCES macro into a list
# of object files.
#
# The CXXFLAGS macro contains a list of options to be passed to
# the compiler. Adding "-g" to this line will cause the compiler
# to add debugging information to the executable.
#
# The CXX macro defines the C++ compiler.
#
# The LDFLAGS macro contains all of the library and library
# directory information to be passed to the linker.
#
CXXSOURCES = basic_sample.cpp # list of source files
CXXOBJECTS = $(CXXSOURCES:.cpp=.o) # expands to list of object files
CXXFLAGS = -DESRI_UNIX $(INCLUDEDIRS)
CXX = g++
LDFLAGS = $(LIBDIRS) $(LIBS)
#
# Default target: the first target is the default target.
# Just type "make -f Makefile.Linux" to build it.
#
all: $(PROGRAM)
#
# Link target: automatically builds its object dependencies before
# executing its link command.
#
$(PROGRAM): $(CXXOBJECTS)
$(CXX) -o $@ $(CXXOBJECTS) $(LDFLAGS)
#
# Object targets: rules that define objects, their dependencies, and
# a list of commands for compilation.
#
basic_sample.o: basic_sample.cpp basic_sample.h
$(CXX) $(CXXFLAGS) -c -o basic_sample.o basic_sample.cpp
#
# Clean target: "make -f Makefile.Linux clean" to remove unwanted objects and executables.
#
clean:
$(RM) -f $(CXXOBJECTS) $(PROGRAM)
#
# Run target: "make -f Makefile.Linux run" to execute the application
# You will need to add $(VARIABLE_NAME) for any command line parameters
# that you defined earlier in this file.
#
run:
./$(PROGRAM)
심지현의 ExaLogs는 Apache-CXF, SOAPUI, Apache-Tomcat, WebLogic, Hadoop, HBase, Zookeeper, Redis, MongoDB, PostgreSQL, Oracle, MySQL ,Spring, XMPP, C++, JAVA 등의 내용을 다룹니다.
2010년 1월 21일 목요일
C++ Linux MakeFile
2010년 1월 20일 수요일
Proftpd와 mysql 연동한 사용자 관리
FTP를 사용하여 데이터 저장 서버를 만들려고 한다.
도전 과제는 다양한 사용자가 존재할 수 있고, 사용자 정보 즉, 추가 삭제가 빈번히 일어난다.
중앙에서 FTP서버에 접속하는 계정을 관리, 유지 하고 싶다.
기본적으로 FTP는 리눅스의 쉘 계정을 사용한다.
FTP유저를 추가하고 싶다면 쉘에 계정을 추가해야하는데..
이거 쫌 보안에 민감하지 않을 수 없다.
그래서 선택한것이 mysql 의 데이터베이스를 사용하여 가상 계정을 만들어 FTP사용을 제어 하는것이다.
찾아본 결과로는 아주 만족스럽게 모든것이 제어가 가능하다.
원하면 쿼터도 조절가능하나, 현재 나의 서비스에서는 필요가 없기때문에 기본적으로 proftp와 mysql 을 연결하여 조절하는 작업을 설명해보겠다.
찾아보면 기본적인 설정에 대한 문서는 어느정도 공개 되어있다.
proftp의 한글 사이트까지 있으나, 단순한 매뉴얼 번역일뿐.. 예제가 없어.. 처음 사용하는데에는 많은 시행착오가 필요할듯 한다.
그래서 여기에 하나의 예제를 만들고자 한다.
그럼 연동 작업 시작합니다.
기본적으로 proftp와 mysql 을 설치 해야한다. (당연하죠?)
이때 중요한 작업이 proftp를 설치할때 mysql을 사용하여 연동할것이라는것을 알려줘야한다.
./configure 할때
다음 옵션을 추가한다.
--with-modules=mod_sql:mod_sql_mysql --with-includes=/usr/include/mysql
즉 ./configure --with-modules=mod_sql:mod_sql_mysql --with-includes=/usr/include/mysql 그밖의 자신의 옵션들...
또는
./configure --prefix=/usr/local/proftpd --with-modules=mod_sql:mod_sql_mysql --with-includes=/usr/include/mysql --with-libraries=/usr/lib --enable-autoshadow --enable-shadow
이렇게 설정하면 된다. 자세한 설치 작업에 대한것은 이곳에서 설명하지 않기로 하겠다.
mysql에서 특별히 할것이 없다. 그냥 기존에 설치 되어있으면 된다.
Step 1
이제 DB에 관리를 할 사용자와 그룹 테이블을 만들겠다.
create table users (
userid char(12) not null,
uid integer unsigned,
gid integer unsigned,
passwd char(63),
shell char(255),
homedir char(255),
count integer unsigned not null,
access_time datetime NOT NULL,
valid integer unsigned,
primary key (userid)
);
create table groups (
gname char(12) not null,
gid integer unsigned,
members text,
primary key(gname)
);
userid char(12) not null,
uid integer unsigned,
gid integer unsigned,
passwd char(63),
shell char(255),
homedir char(255),
count integer unsigned not null,
access_time datetime NOT NULL,
valid integer unsigned,
primary key (userid)
);
create table groups (
gname char(12) not null,
gid integer unsigned,
members text,
primary key(gname)
);
proftp 매뉴얼에 있는 기본적인 테이블 스키마이다. 여기에 사용자의 최종 접속 시간을 체크하기 위해 access_time 이라는 필드를 추가했다.
Step 2
다음은 모든 가상 계정들을 대신하여 폴더 권한을 가질 계정의 실제 그룹과 유저를 생성하겠다.
> groupadd -g 3001 ftpuser
> useradd -u 3001 -s /sbin/nologin -d /bin/null -c "proftpd user" -g ftpuser ftpuser
> useradd -u 3001 -s /sbin/nologin -d /bin/null -c "proftpd user" -g ftpuser ftpuser
이렇게 좀 떨어진 gid와 uid로 그룹과 유저를 생성한다. 관리의 편리를 위해서다.
중요점! 유저를 생성할때 이 유저는 실제로 사용할 유저가 아니기 때문에 홈디렉토리와 쉘이 없어야 한다.
Step 3
이제 proftp 설정화일을 수정하자.
설정화일을 각 설치 환경마다 다르겠지만, 기본적으로는 설치된 proftp 폴더아래에 etc 폴더아래에 있다.
화일의 맨 아랫부분에 다음 설정을 삽입한다.
각 설정은 설명을 할테니 자신이 원하는 환경에 맞게 수정하면 될것이다.
<Global>
# SQL Authentication
# SQL user
# Mysql 접속 정보이다. 형식은 DB이름@호스트:포트 사용자아이디 사용자패스워드 이다.
SQLConnectInfo test@localhost:3306 ftp ftppass
# 사용자 테이블에 저장될 패스워드의 형식을 결정한다.
# 많이 쓰는것이 mysql 의 PASSWORD() 함수를 사용하는것이다. 이를 위해서는
# 아래 Plaintext를 Backend 로 변경한다. Plaintext는 글자 그대로 텍스트로 저장한것이다.
SQLAuthTypes Plaintext
# 사용자 테이블의 정보를 알려준다.
# 형식은: 테이블이름 아이디필드 패스워드필드 uid gid 홈폴더필드 쉘필드 이다.
# 자신이 만든 테이블의 필드명에 맞게 하나씩 써준다.
SQLUserInfo users userid passwd uid gid homedir shell
# 그룹 테이블의 정보를 알려준다.
# 형식은: 테이블이름 그룹이름 gid 그룹속한사용자 이다.
# members 는 콤마로 각 그룹에 속할 실제 계정 유저를 넣어 주면 된다.
SQLGroupInfo groups gname gid members
# 유저의 사용을 제어하는 쿼리를 만든다.
# 유저 테이블을 보면 valid라는 필드가 있는데 이것이 0인 유저는 로그인 못하고
# 1인 사용자만 로그인 할수 있게 쿼리를 날리기 위한 Where 절을 생성한다.
# 필요에 따라 쿼리를 쓰면 된다.
SQLUserWhereClause "valid = 1"
# 만약 유저 테이블의 homedir 폴더가 없다면 기본적으로 사용한 폴더를 설정한다.
SQLDefaultHomedir "/home/data2/storeftp"
# FTP사용자들은 모두 가상이기 때문에 실제 쉘 계정이 없다.
# 아래를 설정함으로써 쉘이 없어도 ftp에 접속 할수 있게 한다.
RequireValidShell off
# 어떤 인증을 할지를 설정하는데
# 여기서는 유저와 그룹을 체크하는것으로 했다.
# 단순하 FTP에서는 단지 users 만 적어서 사용자 관리만 할 수 있다.
SQLAuthenticate users* groups*
# 최소 GID와 UID로 사용할 번호이다.
# 기본적으로 999 이기 때문에 설정할 필요 없지만.. 보안적인 측면에서 설정하면 좋다.
SQLMinID 3000
# 만약에 유저의 homedir이 없으면 자동으로 생성해주는 설정이다.
# 필요없으면 주석 처리 하면 된다.
CreateHome on
# 이제 부터는 약간의 관리 로그를 작성하는 부분이다.
# 각 쿼리를 이름을 만들수 있다.
# 아래에 보면 getcount 뒤에 SELECT 가 쭉 붙는데.. 이 쿼리가 getcount 라는 이름으로 저장된것으로 보면 된다.
SQLNamedQuery getcount SELECT "count from users where userid='%u'"
SQLNamedQuery updatecount UPDATE "count=count+1, access_time=now() WHERE userid='%u'" users
# 로그인했을때 보여줄 메세지이다. %{getcount}이것은 위에 설정한 쿼리의 결과값을 출력한다.
# 여기서 PASS는 로그인했을때 하라는 부분이다.
SQLShowInfo PASS "230" "%u님은 %{getcount} 번 로그인하셨네요~"
# 즉, PASS일때 위의 메세지를 보여주고 그리고 updatecount 쿼리를 한번 실행하라는것이다.
# updatecount는 위에 정의 했는데 각 유저 테이블의 로그인 횟수를 증가하고 최종 로그인 시간을 저정하는 부분이다.
SQLLog PASS updatecount
# 이부분은 추가적으로 각 사용자의 다운로드와 업로드 부분을 로그 기록하는 것인데,
# 테이블 스키마를 아래에 적어 주겠다.
SQLLog RETR receivefile
SQLNamedQuery receivefile INSERT "null, '%u', '%f', %b, now(), now()" file_download
SQLLog STOR sendfile
SQLNamedQuery sendfile INSERT "null, '%u', '%f', %b, now(), now()" file_upload
</Global>
# 이부분은 ftp사용의 로그를 저장할 화일을 설정하는 부분인데.. 자신의 환경에 맞게 설정하면 된다.
# 아마 기본적으로 TransferLog /var/log/xferlog 이부분을 있을듯하다.
SQLLogFile /var/log/ftpsql
SystemLog /var/log/ftplog
TransferLog /var/log/xferlog
# SQL Authentication
# SQL user
# Mysql 접속 정보이다. 형식은 DB이름@호스트:포트 사용자아이디 사용자패스워드 이다.
SQLConnectInfo test@localhost:3306 ftp ftppass
# 사용자 테이블에 저장될 패스워드의 형식을 결정한다.
# 많이 쓰는것이 mysql 의 PASSWORD() 함수를 사용하는것이다. 이를 위해서는
# 아래 Plaintext를 Backend 로 변경한다. Plaintext는 글자 그대로 텍스트로 저장한것이다.
SQLAuthTypes Plaintext
# 사용자 테이블의 정보를 알려준다.
# 형식은: 테이블이름 아이디필드 패스워드필드 uid gid 홈폴더필드 쉘필드 이다.
# 자신이 만든 테이블의 필드명에 맞게 하나씩 써준다.
SQLUserInfo users userid passwd uid gid homedir shell
# 그룹 테이블의 정보를 알려준다.
# 형식은: 테이블이름 그룹이름 gid 그룹속한사용자 이다.
# members 는 콤마로 각 그룹에 속할 실제 계정 유저를 넣어 주면 된다.
SQLGroupInfo groups gname gid members
# 유저의 사용을 제어하는 쿼리를 만든다.
# 유저 테이블을 보면 valid라는 필드가 있는데 이것이 0인 유저는 로그인 못하고
# 1인 사용자만 로그인 할수 있게 쿼리를 날리기 위한 Where 절을 생성한다.
# 필요에 따라 쿼리를 쓰면 된다.
SQLUserWhereClause "valid = 1"
# 만약 유저 테이블의 homedir 폴더가 없다면 기본적으로 사용한 폴더를 설정한다.
SQLDefaultHomedir "/home/data2/storeftp"
# FTP사용자들은 모두 가상이기 때문에 실제 쉘 계정이 없다.
# 아래를 설정함으로써 쉘이 없어도 ftp에 접속 할수 있게 한다.
RequireValidShell off
# 어떤 인증을 할지를 설정하는데
# 여기서는 유저와 그룹을 체크하는것으로 했다.
# 단순하 FTP에서는 단지 users 만 적어서 사용자 관리만 할 수 있다.
SQLAuthenticate users* groups*
# 최소 GID와 UID로 사용할 번호이다.
# 기본적으로 999 이기 때문에 설정할 필요 없지만.. 보안적인 측면에서 설정하면 좋다.
SQLMinID 3000
# 만약에 유저의 homedir이 없으면 자동으로 생성해주는 설정이다.
# 필요없으면 주석 처리 하면 된다.
CreateHome on
# 이제 부터는 약간의 관리 로그를 작성하는 부분이다.
# 각 쿼리를 이름을 만들수 있다.
# 아래에 보면 getcount 뒤에 SELECT 가 쭉 붙는데.. 이 쿼리가 getcount 라는 이름으로 저장된것으로 보면 된다.
SQLNamedQuery getcount SELECT "count from users where userid='%u'"
SQLNamedQuery updatecount UPDATE "count=count+1, access_time=now() WHERE userid='%u'" users
# 로그인했을때 보여줄 메세지이다. %{getcount}이것은 위에 설정한 쿼리의 결과값을 출력한다.
# 여기서 PASS는 로그인했을때 하라는 부분이다.
SQLShowInfo PASS "230" "%u님은 %{getcount} 번 로그인하셨네요~"
# 즉, PASS일때 위의 메세지를 보여주고 그리고 updatecount 쿼리를 한번 실행하라는것이다.
# updatecount는 위에 정의 했는데 각 유저 테이블의 로그인 횟수를 증가하고 최종 로그인 시간을 저정하는 부분이다.
SQLLog PASS updatecount
# 이부분은 추가적으로 각 사용자의 다운로드와 업로드 부분을 로그 기록하는 것인데,
# 테이블 스키마를 아래에 적어 주겠다.
SQLLog RETR receivefile
SQLNamedQuery receivefile INSERT "null, '%u', '%f', %b, now(), now()" file_download
SQLLog STOR sendfile
SQLNamedQuery sendfile INSERT "null, '%u', '%f', %b, now(), now()" file_upload
</Global>
# 이부분은 ftp사용의 로그를 저장할 화일을 설정하는 부분인데.. 자신의 환경에 맞게 설정하면 된다.
# 아마 기본적으로 TransferLog /var/log/xferlog 이부분을 있을듯하다.
SQLLogFile /var/log/ftpsql
SystemLog /var/log/ftplog
TransferLog /var/log/xferlog
------------------------- 참고--------------------
업로드, 다운로드 관리 테이블
CREATE TABLE `file_download` (
`num` int(11) NOT NULL auto_increment,
`user` varchar(30) NOT NULL,
`file_name` varchar(100) NOT NULL,
`file_size` int(11) NOT NULL,
`file_date` date NOT NULL,
`file_time` time NOT NULL,
PRIMARY KEY (`num`),
KEY `user` (`user`,`file_date`)
) ;
CREATE TABLE `file_upload` (
`num` int(11) NOT NULL auto_increment,
`user` varchar(30) NOT NULL,
`file_name` varchar(100) NOT NULL,
`file_size` int(11) NOT NULL,
`file_date` date NOT NULL,
`file_time` time NOT NULL,
PRIMARY KEY (`num`),
KEY `user` (`user`,`file_date`)
);
업로드, 다운로드 관리 테이블
CREATE TABLE `file_download` (
`num` int(11) NOT NULL auto_increment,
`user` varchar(30) NOT NULL,
`file_name` varchar(100) NOT NULL,
`file_size` int(11) NOT NULL,
`file_date` date NOT NULL,
`file_time` time NOT NULL,
PRIMARY KEY (`num`),
KEY `user` (`user`,`file_date`)
) ;
CREATE TABLE `file_upload` (
`num` int(11) NOT NULL auto_increment,
`user` varchar(30) NOT NULL,
`file_name` varchar(100) NOT NULL,
`file_size` int(11) NOT NULL,
`file_date` date NOT NULL,
`file_time` time NOT NULL,
PRIMARY KEY (`num`),
KEY `user` (`user`,`file_date`)
);
Step 4
실제 사용할 유저를 추가해보자~~
먼저 그룹정보를 추가한다.
INSERT INTO `groups` (`gname`, `gid`, `members`) VALUES ('ftpuser', 3001, 'ftpuser');
여기서 그룹 이름과 gid는 서버의 실제 정보를 입력해야한다.memebers 에서 아까 step2 에서 생성한 실제 유저 정보를 입력한다.
이제는 가상 유저를 추가하자.
INSERT INTO `users` (`userid`, `passwd`, `uid`, `gid`, `homedir`, `shell`, `count`, `accessed_time`, `valid`) VALUES ('test', 'test', 3001, 3001, '/home/ftpuser/test', '/sbin/nologin', 0, '', '' '1');
이렇게 데이터를 추가하면 사용할 유저가 추가된다.여기서 중요점은 이 가상 유저가 사용할 그룹 id 즉, gid를 위에서 설정한 그룹 정보와 맞춰야한다.
그래야 이 가상 유저가 로그인하면 실제 계정인 ftpuser 로 로기인 한것처럼 된것이기 때문이다.
이제 로그인 해보자. FTP 클라이언트 프로그램을 이용하여 설정한 서버로
유저 이름 test 비밀번호 test로 접속해보자.
접속 되면 잘된것이고 안되면.. 다시 설정을 잘 봐야 할것이다.
그리고 실제 서버의 폴더에 가면 /home/ftpuser/test 라는 폴더가 자동 생성되었을것이다.
이상으로 Proftp 와 mysql을 연결하여 계정 관리하는 방법을 설명하였다.
DB에서 계정을 관리하기 때문에 보안적인 측면에서 좋고,
관리도 더욱 쉬워지게 될것이라 생각한다.
참고 자료: http://www.howtoforge.com/proftpd_mysql_virtual_hosting (영문이지만 예제가 잘 나와있다.)
http://www.castaglia.org/proftpd/modules/mod_sql.html (그밖의 설정 화일에 대한 매뉴얼)
http://proftpd.oops.org/ (Proftpd 한글 사용자 모임
21.5.6. MySQL Connector/C++ Tutorials
Setting up the World database for use in the tutorials
These tutorials primarily use the
World
database, so you need to have that installed. You can download the World
database, and documentation on how to install it, from the MySQL Documentation page - look for the section called “Example Databases”. Tutorial framework code
Rather than repeating the same code, a framework is given here. You can reuse this framework with all the tutorials unless otherwise stated. This boiler plate code can then simply be reused for each tutorial.
The framework code is given here:
#include <stdlib.h> #include <iostream> #include <sstream> #include <stdexcept> #include "mysql_connection.h" #include <cppconn/driver.h> #include <cppconn/exception.h> #include <cppconn/resultset.h> #include <cppconn/statement.h> #include <cppconn/prepared_statement.h> #define EXAMPLE_HOST "localhost" #define EXAMPLE_USER "root" #define EXAMPLE_PASS "" #define EXAMPLE_DB "world" using namespace std; int main(int argc, const char **argv) { string url(argc >= 2 ? argv[1] : EXAMPLE_HOST); const string user(argc >= 3 ? argv[2] : EXAMPLE_USER); const string pass(argc >= 4 ? argv[3] : EXAMPLE_PASS); const string database(argc >= 5 ? argv[4] : EXAMPLE_DB); cout << "Connector/C++ tutorial framework..." << endl; cout << endl; try { /* INSERT TUTORIAL CODE HERE! */ } catch (sql::SQLException &e) { /* The MySQL Connector/C++ throws three different exceptions: - sql::MethodNotImplementedException (derived from sql::SQLException) - sql::InvalidArgumentException (derived from sql::SQLException) - sql::SQLException (derived from std::runtime_error) */ cout << "# ERR: SQLException in " << __FILE__; cout << "(" << __FUNCTION__ << ") on line " << __LINE__ << endl; /* Use what() (derived from std::runtime_error) to fetch the error message */ cout << "# ERR: " << e.what(); cout << " (MySQL error code: " << e.getErrorCode(); cout << ", SQLState: " << e.getSQLState() << " )" << endl; return EXIT_FAILURE; } cout << "Done." << endl; return EXIT_SUCCESS; }To compile and run the framework
First, copy and paste the framework code to a file such as
frmwk.cpp
. Edit the #define
statements to reflect your connection details (server, user, password, database). To compile the framework, for example on Mac OS X, type:
shell> g++ -o frmwk -I/usr/local/include -I/usr/local/include/cppconn -lmysqlcppconn frmwk.cppTo run the framework, enter the following:
shell> ./frmwkYou will see a simple message. You are now ready to continue to the tutorials.
MySql 구조도 및 명령어
SQL 구조도
DATABASE –>여러 개의 TABLE -> 여러 개의 필드;
명령어들
-DATABASES-
*SHOW DATABASES; <현재 있는 데이터 베이스 이름을 본다.>
*USE 데이터베이스이름; <데이터베이스이름를 사용한다.>
*CREATE DATABASE 데이터베이스이름; <데이터베이스이름으로 데이터베이스를 만듬.>
*DROP DATABASE 데이터베이스이름; <데이터베이스이름의 데이터베이스를 삭제>
-DATABASE- :USE 데이터베이스이름; 명령으로 사용할 데이터베이스 선택해야함
*CREATE TABLE 테이블이름(구조) <데이터베이스안에 테이블를 만든다.>
Ex) CREATE TABLE aa(id INT AUTO_INCREMENT, name VARCHAR(30), old INT, exp INT, PRIMARY KEY(id));
-> 변수 선언할 때 (변수이름 변수형, ….. )
-> AUTO_INCREMENT 자동추가로 값을 입력할 때 NULL를 넣으면 자동 증가된다.
-> PRIMARY KEY(id) 명령은 테이블 내의 특정 변수를 검색하는데 있어서 데이터베이스를
최적화 하는데 사용된다. 뒤에 in는 가장 처음 선언한 변수로써 id를
가장 많이 검색하게 될 것이므로 id를 테이블의 primary key로 설정했다..
*SHOW TABLES; <데이터베이스안에 선언한 테이블 이름이 출력.>
*DECRIBE 테이블이름; <데이터베이스안의 테이블이름의 구조를 본다.>
Ex) DECRIBE aa; 라고 하면 aa라는 테이블 구조가 출력된다.
*INSERT INTO 테이블이름 VALUES (테이블 변수값);
Ex) INSERT INTO aa VALUES (NULL, ‘잭’, 14, 1431), (NULL, ‘룬’, 20, 14342) ;
->문자열 입력할때는 ‘룬’ 처럼 ‘ ‘ 안에 넣도록
*DROP TABLE aa;
데이터베이스 안의 aa 데이블 자체를 지운다.
<SELECT 테이블 데이타 검색>
*SELECT * FROM 테이블이름 <데이터베이스안의 테이블이름 모든 내용 값출력.>
*SELECT 찾는테이블변수이름 FROM 테이블이름
<데이터베이스안의 검색테이블변수이름에 대한 모든 값을 출력>
Ex) SELECT name,exp FROM aa; aa테이블 안의 name과 exp 부분값만 출력
*SELECT * FROM 테이블이름 WHERE 조건; 테이블안에 조건에 맞는 필드만 출력
Ex) SELECT *FROM aa WHERE exp > 1000; aa테이블 안의 exp부분값이 1000이상일것만 출력
확장 => SELECT id,name FROM aa WHERE old = 86; aa테이블 안의 old값이 86인것만 id과 name를 출력
=> SELECT * FROM aa WHERE old > 86 AND old<20; AND 명령어로 조건을 추가할 수 있다.
*SELECT * FROM aa WHERE name LIKE “J%”; <aa테이블의 name내용중 “J”로 시작하는 필드들 출력
=>LIKE는 부분 속하는것이다. 만약 LIKE “%S%” 로 검색하면 S문자가 포함된 모든 값들을 출력한다.
* SELECT * FROM aa WHERE name LIKE “J%” LIMIT 2; =제한.
<aa테이블의 name내용중 “J”로 시작하는 필드를 출력하는데 2개만 출력한다.>
<DELETE FROM 테이블에 필드 삭제. >
*DELETE FROM aa WHERE name = “Jeff”;
<aa테이블에서 이름이 Jeff인 필드를 삭제한다>
*DELETE FROM aa;
<aa테이블 안의 모든 필드를 지운다.>
<ALTER 테이블에 다른 필드 추가. >
*ALTER TABLE aa ADD lastTime TIMESTAMP;
<aa의 테이블안에 lastTime라는 이름에 TIMESTAMP 속성의 필드가 추가된다.>
즉 aa가 (id INT, name VARCHAR(30), old INT, exp INT); 였다면
위 명령실행후
Aa는 (id INT, name VARCHAR(30), old INT, exp INT, lastTime TIMESTAMP) 로 된다는 것이다.
*ALTER TABLE aa MODIFY name VARCHAR(50);
<aa의 테이블 안에 있는 name 변수를 VARCHAR(50)으로 속성을 바꾼다.>
<UPDATE 필드의 데이터 업데이트>
*UPDATA aa SET lasttime =NULL WHERE name = “Jeff”;
<aa의 테이블 안에 있는 name이 “Jeff”이 lasttime 속성의 값을 현재시간으로 업데이트한다.>
(TIMESTAMP는 NULL입력하면 현재시간으로 된다.)>
(만약 직접 입력하고 싶다면 NULL대신 20090722002000 처럼 입력하면된다. 앞에서부터 2009년 07월 22일 00시 20분 00초 이다,)
확장 => 마지막에 LIKE 명령어로 해당 값이 들어간 모든 것에 수정할수 있다.
*UPDATA aa SET lasttime =NULL WHERE name LIKE “J%”;
->이름이 J시작하는 lasttime를 현재시간으로 업데이트한다.
<ORDER BY 출력 순서 정하기 > -기본이 오름차순이다.
*SELECT * FROM aa ORDER BY name; <aa테이블에서 name를 값중심으로 오름차순 정렬한다>
내림차순으로하려면 => *SELECT * FROM aa ORDER BY name DESC;
같은값이 나올 때 또다른 순서 => (ex) old 나이가 같은사람은 다음 경험치로 순서를 정하려면)
*SELECT * FROM aa ORDER BY old,exp;
<마지막 입력된데이터 구하기
1. SELECT @maxid:=MAX(id) FROM aa;
- @명령어로 maxid 이름을 변수를 선언하여 id필드로부터 가장 큰 값을 얻어 저장한다.
2. SELECT *FROM aa WHERE id = @maxid;
- 테이블 aa에서 id값이 maxid에 저장되 최대값인 필드만 출력한다.
*가장 늦은 시간값 구하는 방법
1. 마지막 시간을 가져온다.
SELECT @lastTime:=MAX(lastTime) FROM aa;
2.그 시간을 가지고 검색해서 가져온다.
SELECT * FROM aa WHERE lastTime =@lastTime;
이때 같은 이름을 했지만 지역 변수로 되어 중복되는 것이 아니다.
-기타.
*DB 백업하기 backup.sql 파일 만들기
콘솔화면에서 mysqldump 파일 있는 경로로 가서(보통 sql이 설치된 bin에 있다)
Mysqldump –u root –p DB데이타 이름 > 저장이름.sql
Ex) Mysqldump –u root –p gamedata > gamedata.sql
*gamedata.sql 파일 복원
컨솔화면에서 mysql –u root 넣을데이타베이스이름 < 넣을데이타.sql;
Ex) mysql –u root gamedata <gamedata.sql
중요한건 넣기전에 새로운DB가 없으면 안되니. CREATE DATABASE gamedata; 만들어줄것!
MySql C API Table 과 Record : 추가 삭제 데이터 입력 레코드 찾기
#define SQL_CREATE "CREATE"
#define SQL_DROP "DROP"
#define SQL_TABLE "TABLE"
#define SQL_DATABASE "DATABASE"
////#define SQL_INSERT_RECORD "INSERT INTO playerinfo VALUES(NULL , %s, %d);" //"
#define SQL_INSERT "INSERT"
#define SQL_INTO "INTO"
#define SQL_VALUES "VALUES"
//#define SQL_SELECT_RECORD "SELECT * FROM playerinfo"
#define SQL_SELECT "SELECT"
#define SQL_FROM "FROM"
#define SQL_WHERE "WHERE"
//---------Table----------------------------------
//------------------------------------------------
//테이블리스트를가져온다
BOOL CMySQLDB::GetTableList(MYSQL_RES* &Refresul)
{
MYSQL_RES* result =NULL;
result= mysql_list_tables(m_DBInfo.m_MySQL_CONNECT,"%");
Refresul=result;
if(result)
{
while(result->data->data!=NULL){
printf("있다%s\n",*(result->data->data->data));
result->data->data =result->data->data->next;
}
return TRUE;
}
return FALSE;
}
//테이블생성
BOOL CMySQLDB::CreateTable(const char* TableName,const char* TableStructure)
{
if(!TableName || !TableStructure )
return FALSE;
memset(m_CommandString,0, _countof(m_CommandString));
sprintf_s(m_CommandString,"%s %s %s(%s); ",SQL_CREATE,SQL_TABLE, TableName,TableStructure);
m_dQuery_stat=mysql_query(m_DBInfo.m_MySQL_CONNECT,m_CommandString);
if (m_dQuery_stat != 0)
{
cout<<"여기?"<<endl;
//fprintf(stderr, "Mysql query error : %s", mysql_error(&conn));
return FALSE;
}
cout<<m_CommandString<<endl;
return TRUE;
}
//테이블삭제
BOOL CMySQLDB::DelTable(const char* Tablename)
{
if(!Tablename)
return FALSE;
memset(m_CommandString,0, _countof(m_CommandString));
sprintf_s(m_CommandString,"%s %s %s",SQL_DROP,SQL_TABLE, Tablename);
cout<<m_CommandString<<endl;
m_dQuery_stat=mysql_query(m_DBInfo.m_MySQL_CONNECT,m_CommandString);
if (m_dQuery_stat != 0)
{
return FALSE;
}
/*
query_stat=mysql_query(connection,SQL_DROP_TABLE);
if (query_stat != 0)
{
fprintf(stderr, "Mysql query error : %s", mysql_error(&conn));
}
*/
return TRUE;
}
//---------Record----------------------------------
//------------------------------------------------
//레코드삽입.
BOOL CMySQLDB::INSERTTableValue(const char* TableName,const char *valse , ... )
{
if(!TableName || !valse )
return FALSE;
//레코드에입력값들을스크림으로만든다.
char ValueString[512];
va_list argptr;
va_start( argptr, valse );
vsprintf_s(ValueString, valse, argptr );
va_end( argptr );
memset(m_CommandString,0, _countof(m_CommandString));
sprintf_s(m_CommandString,"%s %s %s %s(%s);",SQL_INSERT,SQL_INTO, TableName,SQL_VALUES,ValueString);
m_dQuery_stat = mysql_query(m_DBInfo.m_MySQL_CONNECT,m_CommandString);
if (m_dQuery_stat != 0)
{
cout<<"여기"<<endl;
// fprintf(stderr, "Mysql query error : %s", mysql_error(&conn));
return FALSE;
}
printf("%s\n",m_CommandString);
return TRUE;
}
//레코드선택 (SELECT valse FROM TableName WHERE condition) ex) "SELECT * FROM playerinfo"
BOOL CMySQLDB::SELECT_FROM_Table(const char* TableName,const char* valse, const char* condition,...)
{
if(!TableName)
return FALSE;
memset(m_CommandString,0, _countof(m_CommandString));
//정렬할변수형들
if(valse == NULL)
{
sprintf_s(m_CommandString,"%s %c %s %s",SQL_SELECT,'*',SQL_FROM,TableName);
}else
{
sprintf_s(m_CommandString,"%s %s %s %s",SQL_SELECT,valse,SQL_FROM,TableName);
}
//찾을조건
if(condition != NULL)
{
char Con[255];
va_list argptr;
va_start( argptr, condition );
vsprintf_s(Con, condition, argptr );
va_end( argptr );
sprintf_s(m_CommandString,"%s %s",m_CommandString, SQL_WHERE ,Con);
}
m_dQuery_stat=mysql_query(m_DBInfo.m_MySQL_CONNECT,m_CommandString);
if (m_dQuery_stat != 0)
{
return FALSE;
}
cout<<m_CommandString<<endl;
return TRUE;
}
//찾은테이블결과값을가져온다..
//레코드보기..sql_result //bool freeReult변수는DB에서Select해서찾은결과값을지울것인지를결정한다.
BOOL CMySQLDB::ViewTableresult(MYSQL_RES* &RefSql_result, bool freeReult)
{
MYSQL_RES *sql_result;
MYSQL_ROW sql_row;
sql_result=mysql_store_result(m_DBInfo.m_MySQL_CONNECT);
RefSql_result=sql_result;
if(freeReult){
while((sql_row=mysql_fetch_row(sql_result))!=NULL)
{
//fiele_count 값이열(col)의(테이블에선언된변수갯수) 이다.
for(int index =0; index<sql_result->field_count ; index++)
{
printf("%s ",sql_row[index]);
}
printf("\n");
}
//mysql_free_result(sql_result);
}
return TRUE;
}
#define SQL_DROP "DROP"
#define SQL_TABLE "TABLE"
#define SQL_DATABASE "DATABASE"
////#define SQL_INSERT_RECORD "INSERT INTO playerinfo VALUES(NULL , %s, %d);" //"
#define SQL_INSERT "INSERT"
#define SQL_INTO "INTO"
#define SQL_VALUES "VALUES"
//#define SQL_SELECT_RECORD "SELECT * FROM playerinfo"
#define SQL_SELECT "SELECT"
#define SQL_FROM "FROM"
#define SQL_WHERE "WHERE"
//---------Table----------------------------------
//------------------------------------------------
//테이블리스트를가져온다
BOOL CMySQLDB::GetTableList(MYSQL_RES* &Refresul)
{
MYSQL_RES* result =NULL;
result= mysql_list_tables(m_DBInfo.m_MySQL_CONNECT,"%");
Refresul=result;
if(result)
{
while(result->data->data!=NULL){
printf("있다%s\n",*(result->data->data->data));
result->data->data =result->data->data->next;
}
return TRUE;
}
return FALSE;
}
//테이블생성
BOOL CMySQLDB::CreateTable(const char* TableName,const char* TableStructure)
{
if(!TableName || !TableStructure )
return FALSE;
memset(m_CommandString,0, _countof(m_CommandString));
sprintf_s(m_CommandString,"%s %s %s(%s); ",SQL_CREATE,SQL_TABLE, TableName,TableStructure);
m_dQuery_stat=mysql_query(m_DBInfo.m_MySQL_CONNECT,m_CommandString);
if (m_dQuery_stat != 0)
{
cout<<"여기?"<<endl;
//fprintf(stderr, "Mysql query error : %s", mysql_error(&conn));
return FALSE;
}
cout<<m_CommandString<<endl;
return TRUE;
}
//테이블삭제
BOOL CMySQLDB::DelTable(const char* Tablename)
{
if(!Tablename)
return FALSE;
memset(m_CommandString,0, _countof(m_CommandString));
sprintf_s(m_CommandString,"%s %s %s",SQL_DROP,SQL_TABLE, Tablename);
cout<<m_CommandString<<endl;
m_dQuery_stat=mysql_query(m_DBInfo.m_MySQL_CONNECT,m_CommandString);
if (m_dQuery_stat != 0)
{
return FALSE;
}
/*
query_stat=mysql_query(connection,SQL_DROP_TABLE);
if (query_stat != 0)
{
fprintf(stderr, "Mysql query error : %s", mysql_error(&conn));
}
*/
return TRUE;
}
//---------Record----------------------------------
//------------------------------------------------
//레코드삽입.
BOOL CMySQLDB::INSERTTableValue(const char* TableName,const char *valse , ... )
{
if(!TableName || !valse )
return FALSE;
//레코드에입력값들을스크림으로만든다.
char ValueString[512];
va_list argptr;
va_start( argptr, valse );
vsprintf_s(ValueString, valse, argptr );
va_end( argptr );
memset(m_CommandString,0, _countof(m_CommandString));
sprintf_s(m_CommandString,"%s %s %s %s(%s);",SQL_INSERT,SQL_INTO, TableName,SQL_VALUES,ValueString);
m_dQuery_stat = mysql_query(m_DBInfo.m_MySQL_CONNECT,m_CommandString);
if (m_dQuery_stat != 0)
{
cout<<"여기"<<endl;
// fprintf(stderr, "Mysql query error : %s", mysql_error(&conn));
return FALSE;
}
printf("%s\n",m_CommandString);
return TRUE;
}
//레코드선택 (SELECT valse FROM TableName WHERE condition) ex) "SELECT * FROM playerinfo"
BOOL CMySQLDB::SELECT_FROM_Table(const char* TableName,const char* valse, const char* condition,...)
{
if(!TableName)
return FALSE;
memset(m_CommandString,0, _countof(m_CommandString));
//정렬할변수형들
if(valse == NULL)
{
sprintf_s(m_CommandString,"%s %c %s %s",SQL_SELECT,'*',SQL_FROM,TableName);
}else
{
sprintf_s(m_CommandString,"%s %s %s %s",SQL_SELECT,valse,SQL_FROM,TableName);
}
//찾을조건
if(condition != NULL)
{
char Con[255];
va_list argptr;
va_start( argptr, condition );
vsprintf_s(Con, condition, argptr );
va_end( argptr );
sprintf_s(m_CommandString,"%s %s",m_CommandString, SQL_WHERE ,Con);
}
m_dQuery_stat=mysql_query(m_DBInfo.m_MySQL_CONNECT,m_CommandString);
if (m_dQuery_stat != 0)
{
return FALSE;
}
cout<<m_CommandString<<endl;
return TRUE;
}
//찾은테이블결과값을가져온다..
//레코드보기..sql_result //bool freeReult변수는DB에서Select해서찾은결과값을지울것인지를결정한다.
BOOL CMySQLDB::ViewTableresult(MYSQL_RES* &RefSql_result, bool freeReult)
{
MYSQL_RES *sql_result;
MYSQL_ROW sql_row;
sql_result=mysql_store_result(m_DBInfo.m_MySQL_CONNECT);
RefSql_result=sql_result;
if(freeReult){
while((sql_row=mysql_fetch_row(sql_result))!=NULL)
{
//fiele_count 값이열(col)의(테이블에선언된변수갯수) 이다.
for(int index =0; index<sql_result->field_count ; index++)
{
printf("%s ",sql_row[index]);
}
printf("\n");
}
//mysql_free_result(sql_result);
}
return TRUE;
}
피드 구독하기:
글 (Atom)