본문 바로가기
DBMS

[Oracle] 웹크롤링_샘플데이터처리

by amoomar 2022. 1. 25.
반응형

 

이번 포스팅에서는 크롤링을 통해 필요한 샘플데이터를 웹에서 불러온 후 TableDB에 필요한 형식에 맞춰 저장하는 방법에 대해 다루었다.

 


 

 

1. DB전달

: 크롤링한 데이터를 필요한 형식에 맞추어 TableDB로 불러오는 작업은 두개의 방법으로 가능하며, 각 방법마다 정리된 순서로 진행되었다.

 

지니에서 인기차트를 크롤링하여 제목, 가수로 구분하고, 이를 컬렉션을 통해 DB로 전달하는 실습예제이다.

두 과정에서 TableDB는 이미 생성을 해둔 후 시작한다.

 

크롤링의 가능여부는 최상위경로에 /robots.txt를 붙여 확인할 수 있다.

 

1) 방법 1

: VO가 없이 진행된다.

 

  ① 크롤링

  1. 밑작업 : 데이터를 가져오는 작업까지를 완료한다.
    final String url="https://www.genie.co.kr/";
    Document doc=null;
    
    try {
    	doc=Jsoup.connect(url).get();
    } catch (IOException e) {
    	// TODO Auto-generated catch block
    	e.printStackTrace();
    }
    
    Elements eles=doc.select("table.list-wrap > tbody > tr.list > td.info > a");
    Iterator<Element> itr=eles.iterator();
  2. 출력을 통해 가져온 데이터 확인
    //cnt를 이용하여 element가 itr에 어떻게 담겨있는지 알 수 있다.
    int cnt = 0;
    while(itr.hasNext()) {
    	System.out.println(cnt +" "+itr.next().text());
    	cnt++;
    	if(cnt==3) {
    		cnt=0;
    	}
    }​

    총 10곡의 정보를 불러왔으며, 아래의 내용은 생략하였다.

 

  ② DB전달

  : 위의 과정을 포함하여 서식을 통째로 조회할 수 있도록 하였다.

package class01;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Iterator;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class Test01 {

	public static void main(String[] args) {

		//[DB전달_상단작업]
		final String driverName="oracle.jdbc.driver.OracleDriver";
		final String dburl="jdbc:oracle:thin:@localhost:1521:xe";
		final String user="ham";
		final String passwd="1234";
		Connection conn=null;
		PreparedStatement pstmt=null;
		String sql="insert into music values((select nvl(max(id),0)+1 from music),?,?)";
		try {
			Class.forName(driverName);
			conn=DriverManager.getConnection(dburl, user, passwd);
			pstmt=conn.prepareStatement(sql);
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}      

		// [크롤링작업]
		final String url="https://www.genie.co.kr/";
		Document doc=null;

		try {
			doc=Jsoup.connect(url).get();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		Elements eles=doc.select("table.list-wrap > tbody > tr.list > td.info > a");
		Iterator<Element> itr=eles.iterator();
		
		// [DB전달_하단작업]
		int cnt=0;
		String a = ""; //제목을 담을 공간
		String b = ""; //가수를 담을 공간
		
		while(itr.hasNext()) {
			String str=itr.next().text();
			System.out.println(cnt+" "+str);
			if(cnt==1) { // 제목
				a=str;
			} else if(cnt==2) { // 가수
				b=str;
				System.out.println(a + " | "+b);
				try {
					pstmt.setString(1, a);
					pstmt.setString(2, b);
					pstmt.executeUpdate();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			cnt++;
			if(cnt==3) {
				cnt=0;
			}
		}
		
		try {
			conn.close();
			pstmt.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}

 

[출력결과]

 

 


 

2) 방법 2

: VO를 활용하여 값을 전달하는 방식으로 진행된다. VO의 생성은 간단하므로 생략하였다.

 

  ① 크롤링

// 1. 크롤링작업
// 최상위경로인 robot.txt로 크롤링 가능여부 확인
final String url="https://www.genie.co.kr/";
Document doc=null;

try {
	doc=Jsoup.connect(url).get();
    } catch (IOException e) {
		e.printStackTrace();
	}

Elements eles=doc.select("table.list-wrap > tbody > tr.list > td.info > a");
Iterator<Element> itr=eles.iterator(); //제네릭에 유의 : 이터레이터 안에는 element가 들어있다!

// 컬렉션을 통해 VO에 title과 singer를 전달
ArrayList<MusicVO> datas=new ArrayList<MusicVO>();
while(itr.hasNext()) {// 값 있냐?
	MusicVO vo = new MusicVO();
	itr.next().text(); // 빈칸은 그냥 버리고,
	vo.setTitle(itr.next().text()); //다음칸은 제목
	vo.setSinger(itr.next().text()); //다음칸은 가수
    
	// vo에 전달 잘 됐으면 그걸 리스트에 담기
	datas.add(vo); // 10번 add됨
	// 값이 3개씩 총 10개!
	// (cnt를 통해 컨트롤 가능)
		}

 

  ② DB전달

  : ①의 작업 하단부에서 바로 진행된다.

 

// 2. DB에 전달하는 작업
final String driverName="oracle.jdbc.driver.OracleDriver";
final String dburl="jdbc:oracle:thin:@localhost:1521:xe";
final String user="ham";
final String passwd="1234";
Connection conn=null;
PreparedStatement pstmt=null;
String sql="insert into music values((select nvl(max(id),0)+1 from music),?,?)";

try {
	Class.forName(driverName);
	conn=DriverManager.getConnection(dburl, user, passwd);
	pstmt=conn.prepareStatement(sql);

	// 10회 반복이 필요하다.
	// 이 10개의 데이터는 datas에 존재,
	// datas는 MusicVO이다.
	for(MusicVO v : datas) {
		pstmt.setString(1, v.getTitle());
		pstmt.setString(2, v.getSinger());
		pstmt.executeUpdate(); //1회에 insert 1회
	}

} catch (Exception e) {
	e.printStackTrace();
} finally {
	try {
		pstmt.close();
		conn.close();
	} catch (SQLException e) {
		e.printStackTrace();
	}
}

 

이 방법또한 정상적으로 tableDB에 저장되는것을 확인할 수 있다.

 

 


 

 

2. 예제

: 예제를 통해 크롤링한 데이터로 MVC구현하였다. 아래는 작업한 순서로 나열한 것이다.

 

1) 설계

: 구상과 함께 미리 패키지와 클래스를 생성해놓았다.

 

CGV의 제품구매 화면에서 제품명, 가격, 상세설명을 스크래핑하여 DB에 전달하고,  MVC를 통해 이 DB에 접근할 수 있도록 하였다.

 

  1. 필요한 구성 결정
    • id : pk
    • name : 제품명
    • price : 가격
    • content : 제품설명
    • cnt : 재고
  2. 각 클래스에서 구현할 내용
    • View
      • 사용자화면 : 상품목록, 상품구매, 종료하기
      • 관리자화면 : 상품목록, 상품등록, 재고추가, 종료하기
    • Model
      • DAO : 핵심로직, 크롤링
      • VO : toString오버라이딩

 


 

2) 크롤링

 

① Utill class생성

  : 작업에 앞서 반복될 내용을 간편하게 관리하기 위할 목적으로 Utill클래스를 생성하였다.

package model;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

// 공통되는 로직을 따로 관리하기 위한 클래스
public class JDBCUtill {
	//static변수를 사용하여 자원으로 선언
	static final String driverName="oracle.jdbc.driver.OracleDriver";
	static final String url="jdbc:oracle:thin:@localhost:1521:xe";
	static final String user="ham";
	static final String passwd="1234";
	
	// DB에 연결 == connection 확보하기에 ouput으로 설정
	public static Connection connect() {
		Connection conn = null;
		try {
			Class.forName(driverName);
			conn=DriverManager.getConnection(url, user, passwd);
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return conn;
	}
	
	// conn, stmt 닫는 메서드
	public static void disconnect(PreparedStatement pstmt, Connection conn) {
		try {
			pstmt.close();
			conn.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}

 

② 크롤링_DB에 전달까지

  : modelDAO생성자에서 작업하여 DAO초기화시(test화면에서 컨트롤러 작동시) 데이터가 자동으로 DB에 전달되도록 구현

// dao생성자에서 크롤링 작업!
public SoupDAO() {
	final String url="http://www.cgv.co.kr/culture-event/popcorn-store/";
	String sql="insert into soup values((select nvl(max(id),0)+1 from soup),?,?,?,?)";
	Document doc=null;

	try {
		doc=Jsoup.connect(url).get();
	} catch (IOException e) {
		e.printStackTrace();
	}

	// select의 아웃풋은 elements로, 여러개의 속성을 선택해올 수 있다.(쉼표로 추가)
	// 즉, span.best_product_text_wrap의 하위 요소들 3개를 불러온 것이다.
	Elements eles=doc.select("span.best_product_text_wrap > span.best_product_text_title, "
		+ "span.best_product_text_name, span.store_deatail_source_price");
	Iterator<Element> itr=eles.iterator(); //제네릭에 유의 : 이터레이터 안에는 element가 들어있다!

	// 컬렉션을 통해 VO에 전달
	ArrayList<SoupVO> datas=new ArrayList<SoupVO>();
	while(itr.hasNext()) {// 값 있냐?
		SoupVO vo = new SoupVO();
		vo.setName(itr.next().text());//제품명
		vo.setContent(itr.next().text()); //상세설명
		//가격
		String str = itr.next().text();
		if(str.equals("금액충전형")) {
			vo.setPrice(0);
		}else {
			vo.setPrice(Integer.parseInt(str.replace(",","")));
		}
		// vo에 전달 잘 됐으면 그걸 리스트에 담기
		datas.add(vo);
	}
		
	// 2. DB에 전달하는 작업
	conn = JDBCUtill.connect();
	try {
		pstmt = conn.prepareStatement(sql);
			
		// datas는 SoupVO이다.
		for(SoupVO v : datas) {
		pstmt.setString(1,v.getName());
           	pstmt.setInt(2, v.getPrice());
            	pstmt.setString(3, v.getContent());
            	pstmt.setInt(4, v.getCnt());
            	pstmt.executeUpdate(); //1회에 insert 1회
		}
			
	} catch (SQLException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} finally {
		JDBCUtill.disconnect(pstmt, conn);
	}

}

 

 

* 여러개의 요소를 가져오는 방법 * 

// select의 아웃풋은 elements로, 여러개의 속성을 선택해올 수 있다.(쉼표로 추가)
// 즉, span.best_product_text_wrap의 하위 요소들 3개를 불러온 것이다.
Elements eles=doc.select("span.best_product_text_wrap > span.best_product_text_title, "
	+ "span.best_product_text_name, span.store_deatail_source_price");
Iterator<Element> itr=eles.iterator(); //제네릭에 유의 : 이터레이터 안에는 element가 들어있다!

: span.best_product_text_wrap 내부에 각각 속하여있는 span들을 쉼표를 통해 3개 불러온 결과

 

Elements eles = doc.select("div > li");
// 받아온 정보 중 요소(태그) 선택
Iterator<Element> itr = eles.iterator(); // 이터레이터로 요소 불러오기
Iterator<Element> itr2= eles.select("dt > a").iterator();
Iterator<Element> itr3= eles.select("span.num").iterator();
Iterator<Element> itr4= eles.select("a > span.num2 > em").iterator();

: div > li 내부에 각각 속하여있는 a , span, em을 이터레이터를 통해 각각 불러오기. 이럴 경우 itr.hasnext( )를 각각에 맞게 반복하여 알맞는 값을 삽입한다.

 

 


 

3) MVC작업

 

① view

package view;

import java.util.ArrayList;
import java.util.Scanner;

import model.SoupVO;

public class SoupView {
	
	Scanner sc = new Scanner(System.in);
	public int action;
	String userMainMsg = "1. 제품목록 \n2. 제품구매 \n3. 종료하기";
	String adminMainMsg = "1. 재고목록 \n2. 상품추가 \n3. 재고추가 \n4. 종료하기";
	
	//사용자 메인
	public void usertView(){
			System.out.println("===사용자 페이지===");
			System.out.println(userMainMsg);
			System.out.println("==============");
			System.out.print(">>");
			action = sc.nextInt();
	}
	
	//관리자 메인
	public void adminView() {
		System.out.println("===관리자 페이지===");
		System.out.println(adminMainMsg);
		System.out.println("==============");
		System.out.print(">>");
		action = sc.nextInt();
	}
	
	//목록페이지
	public void list(ArrayList<SoupVO>datas) {
		System.out.println("===목록===");
		for(SoupVO v :datas) {
			System.out.println(v);
		}
		System.out.println("==========");
	}
	
	//구매페이지
	public SoupVO buy() {
		SoupVO vo = new SoupVO();
		System.out.print("상품번호 : ");
		int id = sc.nextInt();
		System.out.print("구매수량 : ");
		int cnt = sc.nextInt();
		vo.setId(id);
		vo.setCnt(cnt);
		return vo;
	}
	public void buySuccess() {
		System.out.println("구매 성공");
	}
	public void buyFail() {
		System.out.println("구매 실패");
	}
	
	// 상품추가페이지
	public SoupVO addSoup() {
		SoupVO vo = new SoupVO();
		System.out.print("상품명 : ");
		String name = sc.next();
		System.out.print("가격 : ");
		int price = sc.nextInt();
		System.out.print("상세설명 : ");
		String content = sc.next();
		System.out.print("재고수량 : ");
		int cnt = sc.nextInt();
		vo.setName(name);
		vo.setPrice(price);
		vo.setContent(content);
		vo.setCnt(cnt);
		return vo;
	}
	public void addSoupSuccess() {
		System.out.println("상품등록 성공");
	}
	public void addSoupFail() {
		System.out.println("상품등록 실패");
	}
	
	// 재고추가페이지
	public SoupVO addCnt() {
		SoupVO vo = new SoupVO();
		System.out.print("상품번호 : ");
		int id = sc.nextInt();
		System.out.print("추가재고 : ");
		int cnt = sc.nextInt();
		vo.setId(id);
		vo.setCnt(cnt);
		return vo;
	}
	public void addCntSuccess() {
		System.out.println("재고추가 성공");
	}
	public void addCntFail() {
		System.out.println("재고추가 실패");
	}
	
	// 종료페이지
	public void end() {
		System.out.println("페이지가 종료됩니다");
	}
	
}


② model

package model;

import java.sql.ResultSet;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import model.SoupVO;

public class SoupDAO {

	Connection conn;
	PreparedStatement pstmt;

	//비즈니스메소드가 사용할 sql문
	final String selectAll = "select * from soup";
	final String selectOne = "select * from soup where id=?";
	final String updateUser = "update soup set cnt=cnt-? where id=?";
	final String updateAdmin = "update soup set cnt=cnt+? where id=?";
	final String insert = "insert into soup (id,name,price, content, cnt) values((select nvl(max(id),0)+1 from soup),?,?,?,?)";

	// dao생성자에서 크롤링 작업!
	public SoupDAO() {
		final String url="http://www.cgv.co.kr/culture-event/popcorn-store/";
		String sql="insert into soup values((select nvl(max(id),0)+1 from soup),?,?,?,?)";
		Document doc=null;

		try {
			doc=Jsoup.connect(url).get();
		} catch (IOException e) {
			e.printStackTrace();
		}

		// select의 아웃풋은 elements로, 여러개의 속성을 선택해올 수 있다.(쉼표로 추가)
		// 즉, span.best_product_text_wrap의 하위 요소들 3개를 불러온 것이다.
		Elements eles=doc.select("span.best_product_text_wrap > span.best_product_text_title, "
				+ "span.best_product_text_name, span.store_deatail_source_price");
		Iterator<Element> itr=eles.iterator(); //제네릭에 유의 : 이터레이터 안에는 element가 들어있다!

		// 컬렉션을 통해 VO에 전달
		ArrayList<SoupVO> datas=new ArrayList<SoupVO>();
		while(itr.hasNext()) {// 값 있냐?
			SoupVO vo = new SoupVO();
			vo.setName(itr.next().text());//제품명
			vo.setContent(itr.next().text()); //상세설명
			//가격
			String str = itr.next().text();
			if(str.equals("금액충전형")) {
				vo.setPrice(0);
			}else {
				vo.setPrice(Integer.parseInt(str.replace(",","")));
			}
			// vo에 전달 잘 됐으면 그걸 리스트에 담기
			datas.add(vo);
		}
		
		// 2. DB에 전달하는 작업
		conn = JDBCUtill.connect();
		try {
			pstmt = conn.prepareStatement(sql);
			
			// datas는 SoupVO이다.
			for(SoupVO v : datas) {
			pstmt.setString(1,v.getName());
            		pstmt.setInt(2, v.getPrice());
            		pstmt.setString(3, v.getContent());
            		pstmt.setInt(4, v.getCnt());
            		pstmt.executeUpdate(); //1회에 insert 1회
			}
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			JDBCUtill.disconnect(pstmt, conn);
		}

	}
	// 목록보기
	public ArrayList<SoupVO> selectAll(SoupVO vo) {
		ArrayList<SoupVO> datas = new ArrayList<SoupVO>();
		conn = JDBCUtill.connect();

		try {
			pstmt = conn.prepareStatement(selectAll);
			ResultSet rs = pstmt.executeQuery();

			while(rs.next()) {
				SoupVO data = new SoupVO();
				data.setId(rs.getInt("id"));
				data.setName(rs.getString("name"));
				data.setPrice(rs.getInt("price"));
				data.setContent(rs.getString("content"));
				data.setCnt(rs.getInt("cnt"));
				datas.add(data);
			}

			rs.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			JDBCUtill.disconnect(pstmt, conn);
		}
		System.out.println("dao로그 : 조회 성공");
		return datas;
	}

	// 제품구매
	public boolean updateUser(SoupVO vo) {
		conn = JDBCUtill.connect();
		try {
			conn.setAutoCommit(false);

			pstmt = conn.prepareStatement(updateUser);
			pstmt.setInt(1, vo.getCnt());
			pstmt.setInt(2, vo.getId());
			int res = pstmt.executeUpdate();

			if(res==0) {
				System.out.println("dao로그 : id조회실패");
				return false;
			}

			pstmt = conn.prepareStatement(selectOne);
			pstmt.setInt(1, vo.getId());
			ResultSet rs = pstmt.executeQuery();
			rs.next();

			if(rs.getInt("cnt") < 0) { //cnt-? < 0일때
				System.out.println("dao로그 : 사용자구매실패");
				conn.rollback();
			} else {
				System.out.println("dao로그 : 사용자구매성공");
				conn.commit();
			}

			conn.setAutoCommit(true);
			rs.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			System.out.println("dao로그 : 사용자구매실패");
			e.printStackTrace();
			return false;
		} finally {
			JDBCUtill.disconnect(pstmt, conn);
		}
		System.out.println("dao로그 : 사용자구매성공");
		return true;
	}

	// 재고추가
	public boolean updateAdmin(SoupVO vo) {
		conn = JDBCUtill.connect();
		try {
			pstmt = conn.prepareStatement(updateAdmin);
			pstmt.setInt(1, vo.getCnt());
			pstmt.setInt(2, vo.getId());
			int res = pstmt.executeUpdate();

			if(res==0) {
				System.out.println("dao로그 : 관리자id조회 실패");
				return false;
			}

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println("dao로그 : 관리자 재고추가 실패");
			return false;
		}
		System.out.println("dao로그 : 관리자 재고추가 성공");
		return true;
	}

	// 상품등록
	public boolean insert (SoupVO vo) {
		conn = JDBCUtill.connect();

		try {
			pstmt = conn.prepareStatement(insert);
			pstmt.setString(1, vo.getName());
			pstmt.setInt(2, vo.getPrice());
			pstmt.setString(3, vo.getContent());
			pstmt.setInt(4, vo.getCnt());
			pstmt.executeUpdate();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			System.out.println("dao로그 : 등록실패");
			e.printStackTrace();
			return false;
		} finally {
			JDBCUtill.disconnect(pstmt, conn);
		}
		System.out.println("dao로그 : 등록성공");
		return true;
	}
}

 

③ controller

package controller;

import java.util.ArrayList;

import model.SoupDAO;
import model.SoupVO;
import view.SoupView;

public class SoupController {
	SoupDAO dao;
	SoupView view;

	public SoupController(){
		dao = new SoupDAO();
		view = new SoupView();
	}

	public void appStart() {

		while(true) {
			view.usertView();
			if(view.action==1) {
				SoupVO vo = new SoupVO();
				ArrayList<SoupVO> datas = dao.selectAll(vo);
				view.list(datas);
			}else if(view.action==2) {
				SoupVO vo = view.buy();

				if(dao.updateUser(vo)) {
					view.buySuccess();
				}else {
					view.buyFail();
				}
			}else if(view.action==3) {
				view.end();
				break;
			// 관리자모드 전환
			}else {
				while(true) {
					view.adminView();
					if(view.action==1) {
						SoupVO vo = new SoupVO();
						ArrayList<SoupVO> datas = dao.selectAll(vo);
						view.list(datas);
					}else if(view.action==2) {
						SoupVO vo = view.addSoup();
						if(dao.updateAdmin(vo)) {
							view.addSoupSuccess();
						}else {
							view.addSoupFail();
						}
					}else if(view.action==3) {
						SoupVO vo = view.addCnt();
						if(dao.updateAdmin(vo)) {
							view.addCntSuccess();
						}else {
							view.addCntFail();
						}
					}else if(view.action==4) {
						view.end();
						break;
					}
				}
			}

		}

	}
}

 

 


 

4) 실행

package client;

import controller.SoupController;

public class SoupClient {

	public static void main(String[] args) {
		SoupController ctrl = new SoupController();
		ctrl.appStart();
	}
}

 

[실행결과 : -> 입력]

===사용자 페이지===
1. 제품목록 
2. 제품구매 
3. 종료하기
==============
>>5
===관리자 페이지===
1. 재고목록 
2. 상품추가 
3. 재고추가 
4. 종료하기
==============
>>3
상품번호 : 15
추가재고 : 5
dao로그 : 관리자 재고추가 성공
재고추가 성공
===관리자 페이지===
1. 재고목록 
2. 상품추가 
3. 재고추가 
4. 종료하기
==============
>>4
페이지가 종료됩니다
===사용자 페이지===
1. 제품목록 
2. 제품구매 
3. 종료하기
==============
>>2
상품번호 : 15
구매수량 : 2
dao로그 : 사용자구매성공
dao로그 : 사용자구매성공
구매 성공
===사용자 페이지===
1. 제품목록 
2. 제품구매 
3. 종료하기
==============
>>1
dao로그 : 조회 성공
===목록===
[1] 제품명: CGV 영화관람권 | 가격: 11000원 | 상세설명: 즐거운 경험은 CGV에서! | 0개
[2] 제품명: CGV 골드클래스 | 가격: 35000원 | 상세설명: 최고의 관람환경을 제공하는 프리미엄 상영관 | 0개
[3] 제품명: 4DX관람권 | 가격: 19000원 | 상세설명: 오감만족 영화 속 주인공 되기 | 0개
[4] 제품명: IMAX 관람권 | 가격: 16000원 | 상세설명: 사람이 볼 수 있는 최대 영상, IMAX | 0개
[5] 제품명: PACONNIE A형 | 가격: 0원 | 상세설명: 충전형 선불 카드 | 0개
[6] 제품명: PACONNIE B형 | 가격: 0원 | 상세설명: 충전형 선불 카드 | 0개
[7] 제품명: PACONNIE C형 | 가격: 0원 | 상세설명: 충전형 선불 카드 | 0개
[8] 제품명: CGV콤보 | 가격: 9000원 | 상세설명: CGV의 영원한 베스트셀러! | 0개
[9] 제품명: 더블콤보 | 가격: 12000원 | 상세설명: 취향별로 원하는 맛 선택하세요! | 0개
[10] 제품명: 스몰세트 | 가격: 6500원 | 상세설명: 혼영할때 필수품 | 0개
[11] 제품명: 고소팝콘(L) | 가격: 5000원 | 상세설명: 클래식 팝콘 No.1 | 0개
[12] 제품명: 달콤팝콘(L) | 가격: 6000원 | 상세설명: 달콤한 카라멜 향이 가득한 달콤팝콘 | 0개
[13] 제품명: 더블치즈팝콘(L) | 가격: 6000원 | 상세설명: 치즈매니아들 주목! | 0개
[14] 제품명: 탄산음료(M) | 가격: 2500원 | 상세설명: 시원한 탄산음료와 함께 스트레스도 날리세요 | 0개
[15] 제품명: 아메리카노(HOT) | 가격: 3500원 | 상세설명: 현대인의 필수품 | 3개
[16] 제품명: 칠리치즈나쵸 | 가격: 4900원 | 상세설명: 바삭바삭 나쵸, 얼마나 맛있게요? | 0개
==========
===사용자 페이지===
1. 제품목록 
2. 제품구매 
3. 종료하기
==============
>>3
페이지가 종료됩니다

 

 

 

SQL Results

 

 


 

 

 

반응형

'DBMS' 카테고리의 다른 글

[Oracle] 다양한 검색과 출력_Oracle 함수  (0) 2022.01.28
[Oracle] 프로젝트의 설계 & 두개의 TableDB  (0) 2022.01.26
[Oracle] 웹크롤링_기초  (0) 2022.01.24
[Oracle] 트랜잭션  (0) 2022.01.22
[Oracle] pstmt  (0) 2022.01.21