🍀 JSP 문법

 

  • JSP 표현식
<%= 내용 %>

 

 

 

 

🌀 내장객체 request 로 값을 보내고 받는 방식 이해하기

 

checkbox, radio의 경우 값을 여러 개 선택하면 여러 값이 들어있는 배열로 담아 출력한다.

→ 값을 직접 받는 것과는 다르게 처리해줘야 한다.

 

 

RequestMain.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>

<%
    // Date today = new Date();
    // 내장객체
    // request
    // respones
    // out
    // session
    // application
    // pageContext
    // Page
    // config
    // exception
    %>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

	<form action="RequestWebInfo.jsp" method="post">

		<!-- 값을 체크하는 name 속성, 'eng', 'han' 파라메터 역할을 한다 -->
		<!-- 서버로 값을 넘긴다 -->
		영어 : <input type="text" name="eng" value="Bye" /><br /> 한글 : <input
			type="text" name="han" value="잘 가" /><br /> <input type="submit"
			value="POST 방식 전송" />
	</form>
	<br>
	<br>
	<!-- 아이디와 이름은 작성된 값이 value값
	성별과 같은 선택형 폼은 값이 작성되어 넘어오는 것이 아니기때문에 반드시 폼 안에 value 속성이 들어가야 한다. -->

	<form action="RequestParameter.jsp" method="post">
		아이디 : <input type="text" name="id" value="" /><br /> 성별 : <input
			type="radio" name="sex" value="man" />남자 <input type="radio"
			name="sex" value="woman" checked="checked" />여자 <br /> 관심사항 : <input
			type="checkbox" name="favo" value="eco" />경제 <input type="checkbox"
			name="favo" value="pol" checked="checked" />정치 <input
			type="checkbox" name="favo" value="ent" />연예<br /> 자기소개:
		<textarea name="intro" cols="30" rows="4"></textarea>
		<br /> <input type="submit" value="전송하기" />
	</form>

</body>
</html>

 

RequestParameter.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>

<%
// 한글 꺠짐 방지
request.setCharacterEncoding("UTF-8");

// 값 받기

String id = request.getParameter("id");
String sex = request.getParameter("sex");

// checkbox, radio는 값을 하나로 본다
// 베열로 값을 받아온다
String[] favo = request.getParameterValues("favo");
// 배열에 있는 값을 하나씩 가지고 와야 한다
String favoStr = "";
for (int i = 0; i < favo.length; i++) {
	favoStr += favo[i] + ",";
}

String intro = request.getParameter("intro");
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<ul>

		<li><%=id%></li>
		<li><%=sex%></li>
		<li><%=favoStr%></li>
		<li><%=intro%></li>

	</ul>
</body>
</html>

 


어제 했던 부분)

 

어제 처음으로 값을 전송하고 받아보는 예제를 작성해봤다.

오늘은 어제 이 내용을 바탕으로 응용 + 심화

 

RequestWepInfo.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>

<%
request.setCharacterEncoding("UTF-8");
String eng = request.getParameter("eng");
String han = request.getParameter("han");
%>


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>RequestWepInfo 페이지 입니다.</title>
</head>
<body>

	<h1>RequestWepInfo.jsp 페이지</h1>
	영어 :
	<%=eng%>
	<br> 한글 :
	<%=han%>

</body>
</html>

 


 

🌀 Get 방식과 Post 방식의 차이

 

GET 방식 : URL에 파라메터 정보가 노출된다

http://localhost:9999/ImplicitObject/RequestWebInfo.jsp?eng=Hello&han=안녕

POST방식 : URL에 파라메터 정보가 노출되지 않는다

http://localhost:9999/ImplicitObject/RequestWebInfo.jsp

→ 보안적인 측면에서 POST 방식이 유리하다

 

 

🌀 response

페이지 이동 기능

서버페이지가 값을 보내고 직접 결과를 출력하지 않음

넘어오는 데이터를 처리만 해준다.

처리된 결과를 사용자에게 다시 알려준다

 

 

❗️ 페이지 이동 방식 두 가지 

  • request.getRequestDispatcher("이동할 페이지").forward(request,response)
  • response.sendRedirect("이동할 페이지")

 

페이지 이동 방식

 

가장 처음 페이지 URL : http://localhost:9999/ImplicitObject/ResponseMain.jsp

→ 로그인 성공시 (redirect 방식)

http://localhost:9999/ImplicitObject/ResponseWelcome.jsp

→ 로그인 실패 시 (forward 방식)

http://localhost:9999/ImplicitObject/ResponseLogin.jsp

로그인 실패면 main화면으로 가는데 URL 주소가 다르다 → 제어권

if(id.equals("must") && pwd.equals("1234")){
	// 로그인 성공 시
	response.sendRedirect("ResponseWelcome.jsp");
	
}else{
	// 로그인 실패 시
	request.getRequestDispatcher("ResponseMain.jsp").forward(request,response);
}

request 영역에 대한 제어권은 한 페이지가 가진다.

그 페이지에서 제어권을 넘기지 않으면 해당 페이지에 접근할 수 없다.

 

forward(request,response) → request, response에게 페이지 권한(제어권)을 넘겨준다. (위임)

request, response의 데이터를 읽어올 수 있다.

sendRedirect → 페이지 이동만 일어난다. 제어권을 넘겨주지 않음

다른 페이지의 데이터를 읽어올 수 없다.

 

쿼리스트링이 붙은 것은 데이터는 어떤 값으로 읽어오겠다고 지정을 하는 것 → get방식

 

내장객체) 어플리케이션 객체

 

getRealPath : 실제 저장된 파일 경로

 

톰켓에서 실제 데이터를 저장하고 있는 곳

jsp-workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/firstjsp/

 

 

🌀 영역객체

  • page
  • request
  • session
  • application

 

영역객체가 하는 일 → 사용자가 요청한 정보를 저장한다.

저장은 어디에 해야 가장 적절한지 판단

 

범위에 따라 영역객체를 4개로 나눠 놓았다.

 

 

✨ 영역객체의 범위

  • page

→ 1번, 2번, 3번 페이지가 있다면 각 페이지로 넘어갈 때 다른 페이지의 데이터는 사용할 수 없다.

 

Person.js

package common;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Person {
	
	
	// 빈(Bean) 객체 : DTO클래스
	// 반드시 기본형 생성자가 정의되어 있어야 한다.
	// 멤버는 private 해야한다.
	// getter / setter를 정의한다.
	
	private String name;
	private int age;
	public String getName() {
		return name;
	}
}

page 예제와 request 예제에서 사용하는 Person 타입.

 

PageContextMain.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>

<%@ page import="common.Person"%>

<%
    // 페이지 영역 사용
    pageContext.setAttribute("pageInteger", 1000);
    pageContext.setAttribute("pageString", "페이지 영역의 문자열");
    pageContext.setAttribute("pagePerson", new Person("홍길동", 20));
    %>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

	<%
	int pInteger = (Integer)pageContext.getAttribute("pageInteger");
	String pString = (String)pageContext.getAttribute("pageString");
	Person pPerson = (Person)pageContext.getAttribute("pagePerson");
	%>

	<ul>
		<li><%= pInteger %></li>
		<li><%= pString %></li>
		<li><%= pPerson.getName() %>, <%= pPerson.getAge() %></li>
	</ul>
	
	<h2>페이지 이동 후 page영역 읽어오기</h2>
	<a href = "PageLocation.jsp"> PageLocation.jsp 바로가기 </a>
</body>
</html>

 

  • request

→ 하나의 요청에 의해 호출된 페이지와 포워드(요청 전달)된 페이지까지 공유된다.

→ 페이지 이동 시 request 영역으로 제어권을 넘기기 위해선 forward 방식을 사용

→ 범위 : 제어권을 넘기는 페이지

 

RequestMain.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="common.Person" %>
<%
	request.setAttribute("requestString", "request영역의 문자열");
	request.setAttribute("requestPerson", new Person("안중근", 31)); 
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	
	<%
		request.removeAttribute("requestString");
		String rString = (String)request.getAttribute("requestString");
		Person rPerson = (Person)request.getAttribute("requestPerson");
	%>
	
	<p><%=rString %></p>
	<p><%=rPerson.getName() %>,<%=rPerson.getAge() %></p>
	
	<%
		request.getRequestDispatcher("RequestForward.jsp?paramHan=한글&paramEng=English")
		.forward(request,response);
	%>
</body>
</html>

 

SessionLocation.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@page import ="java.util.ArrayList" %>
    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>페이지 이동 후 session 영역의 속성 읽기</h2>
<%
ArrayList<String> lists = (ArrayList<String>)session.getAttribute("lists");

// 향상된 for문
for(String str : lists) {
	out.print(str + "<br/>");
}

%>
</body>
</html>

모든 브라우저가 종료되면 데이터가 날아간다.

 

  • application

→ 어떤 페이지든 상관없이 모든 페이지에서 application 페이지에 저장된 정보를 이용할 수 있다.

동일 도메인에 한해 페이지 이동 중 생성된 정보를 application에 저장하면 프로그램이 종료되어도 남아있다.

→ 톰캣서버가 살아있는 동안 유효함. (서비스가 죽기 전까지 유효)

→ 모든 영역은 필요하면 데이터를 강제로 지울 수 있다.

→ 범위 : 모든 페이지

 

ApplicationMain.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
    <%@page import = "java.util.HashMap" %>
    <%@page import = "java.util.Map" %>
    <%@page import = "common.Person" %>
    
    <%
    Map<String,Person> maps = new HashMap<>();
    maps.put("actor1", new Person("김길동", 30));
    maps.put("actor2", new Person("이순신", 20));
    application.setAttribute("maps", maps);
    %>
    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
application 영역에 속성 저장완료
</body>
</html>

 

ApplicationResult.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@page import = "java.util.Map" %>
    <%@page import = "common.Person" %>
    <%@page import = "java.util.Set" %>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<%
Map<String,Person> maps = (Map<String,Person>)application.getAttribute("maps");

Set<String> keys = maps.keySet();
for (String key : keys){
	Person person = maps.get(key);
	out.print("이름 : " + person.getName() + ", 나이 : " +person.getAge());
	out.print("<br>");
}
%>

</body>
</html>

<!-- 실행하면 오류난다 -->

톰캣서버가 살아있는 동안은 데이터 정보가 남아있지만 톰캣서버를 죽였다 다시 살리면 오류가 뜬다.

 

 

사용자가 편리하게 사용할 수 있는 페이지 : 3페이지

영역객체에 데이터를 집어 넣을 때 : setAttribute

영역객체에 데이터를 읽어올때 : getAttribute

jsp에서는 자바문법을 다루기 때문에 꼭 컬렉션을 알아야한다.

잘 모르겠으면 자바 컬렉션을 공부할 것.

 

 

🍪 쿠키객체

톰캣에서 쿠키라는 객체를 제공

 

클라이언트와 서버 간 통신

통신규약 http

 

정보를 서버쪽에 저장할때도, 클라이언트쪽에 저장할 때도 있음.

클라이언트 쪽에서 서버가 전달한 정보를 저장하는 것을 ‘쿠키’라고 한다.

클라이언트 PC에 보관된 쿠키정보.

 

session → 서버에 저장

쿠키 → 클라이언트에 저장

 

  • 저장 위치: 세션은 서버에, 쿠키는 클라이언트에 저장됩니다.
  • 보안: 세션이 더 안전하며, 쿠키는 클라이언트에서 수정될 수 있습니다.
  • 용량: 세션은 더 많은 데이터를 저장할 수 있으며, 쿠키는 용량 제한이 있습니다.
  • 유효 기간: 세션은 대개 브라우저 세션 동안 유지되며, 쿠키는 설정된 만료 날짜까지 유지될 수 있습니다.

 

response + 쿠키정보 → 생성

request + 쿠키정보 → 가지고 오기

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

	<!-- 이 페이지를 실행하는 것 자체가 요청 -->
	<h1>쿠키 생성</h1>
	<%
Cookie cookie1 = new Cookie("myCookie1", "내가만든쿠키1");
cookie1.setPath(request.getContextPath()); // 경로를 루트로 설정
cookie1.setMaxAge(3600); // 쿠키 유효시간 1시간 <- 초단위
response.addCookie(cookie1); // 응답헤더에 쿠키 정보가 추가되는 동시에 클라이언트에게 넘어간다

Cookie cookie2 = new Cookie("myCooki1e2", "내가만든쿠키2");
cookie2.setPath(request.getContextPath()); // 경로를 루트로 설정
cookie2.setMaxAge(3600); // 쿠키 유효시간 1시간 <- 초단위
response.addCookie(cookie2);
%>

	<h1>쿠키정보 확인</h1>
	<%
	Cookie[] cookies = request.getCookies(); // 헤더영역에 저장된 쿠키정보를 가지고 온다
	if (cookies != null) {
		for (Cookie c : cookies) {
			String cookieName = c.getName();
			String cookieValue = c.getValue();

			out.print(cookieName + "<br>");
			out.print(cookieValue);
		}
	}
	%>

</body>
</html>

f12 키 누르고 어플리케이션 들어가서 쿠키 정보 확인해보기

어느 덧 국비지원 수업 진행율이 50%을 넘어갔다. 학원에서는 이를 기념한다고 학생들 격려 겸 작은 행사도 했는데 

한 반에 노력을 열심히 한 학생 한 명, 성적이 좋은 학생 한 명을 뽑아 상도 줬다. 

이런 행사가 학생 때 이후 처음이라 꽤 귀엽다고 느껴졌는데 운 좋게도 거기서 내가 상을 받았다..(?!)

내가 이 반에서 성적이 가장 좋은 학생일리는 없고 노력을 열심히 했다는 격려를 담은 실력 향상상을 탔다. 

난 여전히 프로그래밍적 사고도 못하고 정리도 잘 못하고,, 응용도 안되서 내가 뭔가 실력이 향상한게 있나 싶으면서 괜히 상이 부담스럽게 느껴지기도 했는데 제일 일찍오고 늦게 가고 혼자 남아서 컴퓨터 앞에서 뭔가 뚜드려대는 모습을 그래도 강사님이 좋게 봐주신 것 같다. 

그리고 가장 결정적인 건 출석률 때문인 것 같다ㅋㅋ 휴가도 있고 조퇴나 쉴 수 있는 명분이야 많지만 그냥 직장다닌다 생각하고 다니다보니 혼자 지각 결석 없이 올출이었다.. 

0점에서 30점으로만 점수가 올라도 사실상 실력 향상은 맞으니 그냥 고맙게 생각하기로 했다. 

 

요 며칠 잘 하려고 하면 할 수록 잘 되지 않고 가만있던 프로그램에서 어제까진 잘 되다가도 오늘은 안되고(이클립스 오류;) 이런 일들이 연달아 터지니 마음이 정말 어지러웠는데 이 모든 것이 결국 나아가는 과정이라고 토닥이고 있다. 

오라클부터 톰캣버전 충돌, 이클립스 오류들을 겪으며 혼자 해결하려 하다 일이 더 꼬이는 것을 보고는 나 혼자 뭘 하려해도 지금은 안될 수 있다는 것을 인정하며 처음 프로그래밍을 배웠던 선생님에게도 찾아가 조언을 구하기도 했다. 

지금은 국비지원 수업을 들으며 전의 프로그래밍 과외 선생님에게 도움을 받기도 한다. 과외 때 내가 배운 것들 중 어떤 걸 잘 이해를 못하는지를 설명하기 위해서라도 국비지원 수업을 더 잘 듣게 된다. 전에도 나름 잘 들었지만 과외는 돈을 내고 받는거다 보니 한 시간 동안 할 밀도 있는 질문을 뽑아내기 위해 나머지 나날을 꽉꽉 채워야한다. 

이게 정말 내가 모르는게 맞나? 이해할 수 있을 것 같은데.. 이게 더 어려운데 하며 계속 공부를 하게된다. 

나름 공부하는 방법을 찾아가고 있는 것 같다. 

 

 

여러 선생님과 다양한 나이, 환경의 동료들을 만나며 태도의 중요성에 대해 다시 한번 느끼고 점검할 수도 있었다. 

 

 


 

 

뭔가 거창하진 않지만 뭔가를 시작할 때 내가 늘 이 마음이었으면 좋겠다. 작게 깨달은 것들이 생경하면서도 많이 와닿아 적어본다.

 

직무와 자리마다 원하는 태도가 다를 수 있다.

내가 이전에 맡은 일을 잘 해냈다고 그 태도를 쭉 유지하는 것이 모든 사회생활을 잘 할 수 있는 방법이 되는 것은 아니다.

내가 이 직무를 맡기 위해서 어떤 태도로 임해야 하는지 이번에 여러 선생님과 동료를 만나보며 잘 배우자.

 

객관화를 하되, 너무 주눅들지 말자.

 

상황이 변할 수 없으면 내가 변해야한다는 말도 참 좋아하는데 그런 상황 속에서도 내가 지켜야 하는 신념이 있어야 나를 지키며 상황의 흐름을 타고 비로소 서핑을 즐길 수 있는 것 같다. 유연한 태도로 꾸준하게 하다보면 내 자리를 만들 수 있는 날이 오겠지!

 

 

 

 

이 날은 하루 종일 톰캣설치 때문에 쩔쩔맸다. 

맥을 쓰기 때문에 뭔가 설치하거나 환경변수를 설정할때 헤맬 상황을 대비해 미리 공부하고 프로그램 설치도 했었는데.. 

버전이 다 달라서 또 애를 먹고 있다. 자바는 그나마 버전이 범용이라 다행이지만 톰캣이나 스프링부트나.. 혼자 앞서가다가 버전이 달라 버전 충돌일어나고 꼬이는 일들이 몇번이나 발생했다. 잘하려고, 잘해보고 싶어서 수업에 피해주기 싫어서 나름 노력했는데 일이 잘 안풀리니 심란했다. 그래도 나와 비슷한 처지의 사람들이 블로그를 잘 정리해줘서 정말 고맙게 참고했다.

정작 나는 그러지 못하지만.. 그래도 어찌저찌 톰캣 설치! 


 

처음에는 8080포트로 고양이도 뜨고 잘 되는 듯 했지만 강사님이 실제 서버연결은 안된거라해 지우고 다시 깔려다보니 난관에 봉착했다..

터미널에서 cd 명령어도 안먹고 혼자 맨붕이 왔는데 알고보니 띄어쓰기를 제대로 안해서 그런거였다;;

 


firstjsp 라는 파일 만들기

webapp 에서 HelloJsp 라는 파일 만들기, 무조건 여기에 넣어야 한다. 파일들을

<h1>첫번째 jsp 입니다</h1>

IncludeMain 만들기

인클루드 지시자에 대해 배움


강의를 못따라가서 이렇게 들리는 걸 그냥 적어놓으며 나중에 남아 혼자 해봤다ㅋㅋㅠ

 

JSP 문법

내장객체

중요

// request

// respones

// session

// application

// pageContext

 

 

🌀 request

서버로 값을 넘겨주는 내장객체

폼으로 값을 받는 것은 최종값이 값으로 정해진다

 

 

값을 보내는 방식

  • Get : 데이터 조회 요청 (default)
  • Post : 데이터 생성 요청
  • Put : 데이터 수정 요청
  • Delete : 데이터 삭제 요청

 

 

클라이언트와 서버

request 객체는 클라이언트가 보낸 정보 저장, 서버가 요청한 정보도 읽어온다.

 

request 방식의 한글깨짐 현상 해결

request.setCharacterEncoding("UTF-8");

 

이 날은 톰캣설치의 혼란으로 (사실상 혼자만의 생쇼) 정리한게 이게 다 였다.. 

이제 무사히 설치를 했으니 다시 수업에 잘 집중하자!

컴퓨터 재시작 했을 때

colima start --memory 4 --arch x86_64

docker start oracle


맥북 톰캣 설치

/Applications/apache-tomcat-10.1.24 → 톰캣경로

/Applications/apache-tomcat-9.0.89

/Users/yunakang/apache-tomcat-10.1.24/bin


 

오늘은 ‘테이블 설계 후 데이터 집어넣기’를 해본다.

 

테이블 설계

 

✨ 논리적 설계

→ 말로 풀어갈 수 있음

-도서(객체)

-속성

  • 도서번호
  • 도서제목
  • 출판사
  • 가격
  • 도서단가
  • 목차

-고객(객체)

-속성

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

두 테이블이 관계를 맺을 수 있다 → 조인

도서와 고객은 주종관계

도서가 있어야 고객이 있다 → 도서가 주, 고객이 종

 

✨ 물리적 설계

→ 테이블 정의서

→ 커럼 이름 정하기

 

도서 컬럼명 - 타입(크기) - 제약조건

  • bookid - number(2) - pk
  • bookname - varchar2(10) - not null
  • publisher - varchar2(20) - not null
  • price - number(8) - not null

 

 

SQL 관계설정

 

 

erdcloud 에서 erd 작성해보기

  • 쿼리문을 자동으로 만들어준다

 

erdcloud에서 만들어준 쿼리문을 이용해 sql developer로 데이터를 넣고 원하는 형식으로 조회해보았다.

CREATE TABLE  subInfor  (
	 subcode 	varchar2(2)		NULL,
	 subname 	varchar2(20)		NOT NULL,
	 teacher 	varchar2(10)		NOT NULL
);

CREATE TABLE  studentInfor  (
	 no 	number(4)		NOT NULL,
	 name 	varchar2(10)		NOT NULL,
	 department 	varchar2(15)		NOT NULL
);

CREATE TABLE  CourseInfor  (
	 courseNo 	number(10)		NOT NULL,
	 no 	number(4)		NOT NULL,
	 subcode 	varchar2(2)		NULL
);


ALTER TABLE  subInfor  ADD CONSTRAINT  PK_SUBINFOR  PRIMARY KEY (
	 subcode 
);

ALTER TABLE  studentInfor  ADD CONSTRAINT  PK_STUDENTINFOR  PRIMARY KEY (
	 no 
);

ALTER TABLE  CourseInfor  ADD CONSTRAINT  PK_COURSEINFOR  PRIMARY KEY (
	 courseNo 
);






insert into studentInfor (no, name, department)
values (1, '홍길동' ,'컴공과');

insert into studentInfor (no, name, department)
values (2, '장길산' ,'토목과');

insert into studentInfor (no, name, department)
values (3, '임꺽정' ,'불문과');


insert into subInfor (subcode, subname, teacher)
values ('s1', 'java' ,'조용준');

insert into subInfor (subcode, subname, teacher)
values ('s2', '알고리즘' ,'이몽룡');

insert into subInfor (subcode, subname, teacher)
values ('s3', 'web' ,'성춘향');


insert into CourseInfor (courseNo, no, subcode)
values (1, 1 ,'s1');

insert into CourseInfor (courseNo, no, subcode)
values (2, 1 ,'s2');

insert into CourseInfor (courseNo, no, subcode)
values (3, 2 ,'s2');

insert into CourseInfor (courseNo, no, subcode)
values (4, 2 ,'s3');

commit;

select * from studentInfor;
select * from subInfor;
select * from CourseInfor;


-- 학번, 이름, 과목코드, 과목명, 교수명

select s.no, s.name, e.subcode, sb.subname, sb.teacher
from CourseInfor e join studentInfor s
on e.no = s.no
join subInfor sb
on e.subcode = sb.subcode;

 

조인을 통해 아래와 같은 결과를 출력할 수 있다.

 

 

문장 출력하기

-- 문장 출력하기
set serveroutput on;

 

 

🍀 반복문

-- 반복문의 종류
-- loop(무한반복문), for, while


-- 1부터 10까지 출력하기

-- loop 무한반복문
declare
  n number := 1;
begin
  loop 
  dbms_output.put_line(n);
  n := n + 1; 
  
  -- eixt (반복문 강제 종료)
  if (n > 10) then 
   exit;
  end if;
  
  end loop;
end;
/


-- for문 형식
declare
  
begin
 for 변수 in 시작값.. 끝값 loop
 
 end loop;
end;
/

-- for문
-- 실제로는 숫자를 넣는 경우는 거의 없다

declare
  
begin
 for n in 1..10 loop -- 1부터 10까지 1씩 증가한다. (10번 반복)
  dbms_output.put_line(n);
 end loop;
end;
/

-- 반복문을 사용해 사원들의 정보를 가져오기
-- select 구문은 하나만 가지고 올 수 있다
-- 때문에 반복문을 활용하면 된다.
declare
  vdept dept%rowtype;
begin
  
  for n in 1..4 loop
  
  select * into vdept
  from dept
  where deptno = 10 * n;
  
  dbms_output.put_line(vdept.deptno || ' : ' || vdept.dname || ' : ' || vdept.loc);
  
  end loop;

end;
/

-- while 문
declare
 
begin
while 조건식 loop 

end loop;
end;
/

-- while 문
declare
 n number := 1;
begin
 while n <= 10 loop 
  dbms_output.put_line(n);
  n := n + 1;
 end loop;
end;
/

-- while 문을 사용해 dept 테이블 4개 출력 
declare
 vdept dept%rowtype;
 n number := 1;
begin
 while n <= 4 loop

  select * into vdept
  from dept
  where deptno = 10 * n; 
  
  dbms_output.put_line(vdept.deptno || ' : ' || vdept.dname || ' : ' || vdept.loc);
 
  n := n + 1;
end loop;

end;
/

 

 

🍀 저장 프로시져

-- 저장 프로시져
-- 누구든 권한만 가지고 있으면 이 프로시져를 사용할 수 있다

create [or replace] procedure 프로시져명 [(매개변수1, 매개변수2, 매개변수3,...)]

is
 변수
begin

end;
/
-- 데이터 삭제 프로시져
create or replace procedure del_all

is

begin
 delete from emp01;
end;
/

select * from emp01;

-- 프로시져 실행
execute del_all;

 

 

  • 문제 풀어보기

— sel_all 이란 이름의 저장프로시져 만들기

— dept 테이블의 레코드 모두 조회해서 출력

create or replace procedure sel_all

is
 vdept dept%rowtype;
 n number := 1;
begin

 while n <= 4 loop

begin 
 select * into vdept
 from dept
 where deptno = 10 * n; 
 
 dbms_output.put_line(vdept.deptno || ' : ' || vdept.dname || ' : ' || vdept.loc);
 
 end;
 
 n := n + 1;
end loop;
 
end;
/

select * from dept;

execute sel_all;

 

 

🍀 매개변수를 사용하는 프로시저

-- 매개변수를 사용하는 프로시저
-- in, out, in out 총 3가지 형태
-- 기본은 in 타입, 필요하면 out 타입
-- in은 데이터를 받고, out은 데이터를 호출, in out은 둘다 가능

-- 특정데이터만 골라서 삭제하는 프로시저
create or replace procedure del_ename(vename emp01.ename%type)
is

begin
 delete from emp01
 where ename = vename;
end;
/

execute del_ename('SMITH');

select * from emp01;

-- 매개변수 in , out 타입
create or replace procedure sel_empno
(
 vempno in emp.empno%type,
 vename out emp.ename%type,
 vsal out emp.sal%type,
 vjob out emp.job%type
)

is 
 -- 변수
begin
 select ename,sal,job into vename, vsal, vjob
 from emp
 where empno = vempno;
end;
/

-- 실행
-- 바인드 변수
variable var_ename varchar2(15);
variable var_sal number;
variable var_job varchar2(9);


execute sel_empno(7788, :var_ename, :var_sal, :var_job);

print var_ename;
print var_sal;
print var_job;
-- 문제
-- 저장프로시저명 : sel_empname
-- 사워명으로 검색해서 해당사원의 직책을 얻어와서 print 명령어로 값을 출력

create or replace procedure sel_empname
(
 vename in emp.ename%type,
 vjob out emp.job%type
)

is

begin
 select job into vjob
 from emp
 where ename = vename;
end;
/

variable var_job varchar2(9);

execute sel_empname('SCOTT', :var_job);

print var_job;

 

🍀 시퀀스

-- 시퀀스(sequence)
-- 숫자를 자동으로 중복되지 않게 만들어 주는 객체
-- 테이블의 기본키(primary key)가 정의된 컬럼의 값으로 사용
-- 시퀀스명.nextval

create sequence 시퀀스명
start with 1 -- 몇 부터 시작할지 (1부터 하려면 생략 가능)
increment by 1 -- 얼마나 증가할지
maxvalue 10의 27승 -- 최대
minvalue 10의 -27승 -- 최소

 

시퀀스 생성

create sequence emp01_seq
start with 10
increment by 10
maxvalue 10000;

-- 시퀀스 객체의 구조를 확인
-- user_xxx 로 딕셔너리에 접근
desc user_sequences;

select SEQUENCE_NAME, MIN_VALUE, MAX_VALUE, INCREMENT_BY
from user_sequences;

select emp01_seq.nextval
from dual;
-- 실행할 때마다 값이 증가한다

drop table emp01;

create table emp01(
empno number(4) primary key,
ename varchar2(10),
hiredate date
);

insert into emp01
values (emp01_seq.nextval, 'hong', sysdate);

delete from emp01
where empno = 90;

select * from emp01;

새로 데이터가 만들어질 때마다 empno가 증가한다

-- 증가하는 sequence에 별칭 부여
insert into emp01
values ('eno' || emp01_seq.nextval, 'hong', sysdate);

 

 

🍀 인덱스

-- 인덱스(index)
-- 데이터의 조회 속도를 증가 시킨다.
-- 컬럼에 생성하는 객체
-- primary key 제약조건이 정의된 컬럼은 기본적으로 index 객체가 생성 되어있다

-- 조건 : 전체의 3~4% 내외 데이터 검색이 이뤄질 때 효과적이다
-- 인덱스 객체를 만드는 것도 용량을 차지하기 때문에 인덱스 객체가 필요한지 잘 판단하는 것이 중요
-- 실제로는 primary key를 더 많이 사용

drop table emp01;

create table emp01
as
select * from emp;

-- 자기 것을 복제
-- insert into emp01
-- select * from emp01;

select count(*) from emp01;

insert into emp01(empno, ename)
values (1111, 'SYG');

-- 인덱스 객체가 생성되기 전과 후 데이터 찾는 속도 비교
set timing on;

select distinct empno, ename from emp01
where ename = 'SYG';

-- 인덱스 객체 생성
create index idx_emp01_ename
on emp01 (ename);

desc user_ind_columns;

select INDEX_NAME, TABLE_NAME, COLUMN_NAME
from user_ind_columns
where table_name in ('EMP01');

-- 인덱스 삭제
drop index idx_emp01_ename;

데이터를 5만건 넣고 조회하는 속도를 비교해보았다.

 

 

🍀 데이터 베이스 권한

system 계정

-- 데이터 베이스 권한
-- 최고 권한 DBA (system 계정)

-- 계정 생성
-- DCL(Data Control Language)
-- grant : 사용자에게 권한 부여 
-- revoke : 사용자에게 권한 취소

-- 데이터 베이스의 권한을 부여하기 위해 새로운 개정 생성
create user user01 identified by 1234;

-- 권한
-- 시스템 권한
-- 객체 권한

-- 권한 부여 명령어

-- 세션 만들기 권한
grant create session
to user01;

-- 테이블 만들기 권한
grant create table
to user01;

-- 다른 계정의 객체를 사용하고 싶을 때 권한 위임
-- 객체에 따라 권한 목록이 다름

-- 권한 회수
revoke create table
from user01;

 

scott 계정에서 user01 계정으로 권한 부여, 회수

scott 계정

-- 객체 권한
grant select
on emp
to user01;

-- 권한 회수
revoke select
on emp
from user01;

 

user01 계정

create table emp(
empno number(4)
);

drop table emp;

-- 누구로부터 권한을 부여받았는지 명시해줘야 한다 (스키마 붙이기)
select * from scott.emp;

-- 삭제 권한은 없기 때문에 실행되지 않음
-- delete from scott.emp;

desc user_tab_privs_recd;

select * from user_tab_privs_recd;

 

 

role 권한

system 계정

-- role 권한
-- 오라클베이스에 만들어져 있다
-- connect
-- resouce
-- dba

create user user02 identified by 1234;

-- 만들어진 roll을 사용하여 모든 권한 부여
grant connect, resource
to user02;

 

user02 계정

create table test (
empno number(4)
);

테이블이 잘 만들어진다.

 

role 을 직접 만들어서 사용하기

system 계정

-- role 만들어서 사용
create role mrole;

grant create session, create table, create view
to mrole;

create user user03 identified b용y 1234;

grant mrole
to user03;

 

user03 계정

create table test (
empno number(4)
);

테이블이 잘 만들어진다

 

객체권한을 담는 role

system 계정

-- 객체권한을 담는 role
create role mrole2;

-- 권한 주기
grant mrole2
to user03;

revoke mrole2
from user03;

-- role 삭제
-- revoke는 role을 특정사용자로부터 권한 회수, drop은 role을 아예 삭제하는 것이다
drop role mrole2;

 

scott 계정

-- role에 권한 부여
grant select
on emp
to mrole2;

 

user03

create table test (
empno number(4)
);

select * from scott.emp;

 

 

🍀 확장된 SQL 구문

-- PL/SQL (확장된 sql 구문)
-- 변수, 반복문, 조건, 비교문
-- 실행문 마지막에 반드시 세미콜론을 붙인다.

[declare] 
변수
begin

변수의 초기화, 반목문, 조건문, sql구문, 출력함수()

[exception]

end;
/

 

 

변수의 초기화

-- 문장 출력하기
set serveroutput on;

begin
dbms_output.put_line('hello world');
end;
/

-- 변수, 상수 선언

declare
vempno number(4); -- 변수의 선언
vename varchar2(10);
vjob varchar2(10) := 'sales'; -- 선언 및 초기화

begin
vempno := 7788; -- 변수의 초기화
vename := 'HONG';

-- 출력함수
dbms_output.put_line(vempno || ' : ' || vename);
end;
/

-- pl/sql구문
-- select 구문 작성 시 반드시 into절과 where절을 함께 작성해야 한다.
-- where은 조건절이 온다.




declare
	  -- 스칼라 방식
	  -- 타입과 크기를 직접 명시하는 방식
    -- vempno number(4); 
    -- vename varchar2(10);
    
    -- 레퍼런스
     vempno emp.empno%type; -- number(4)
     vename emp.ename%type; -- varchar2(10)
     
begin
    select empno, ename into vempno, vename
    from emp
    where ename = 'SCOTT';
    
    dbms_output.put_line(vempno || ' : ' || vename);
end;
/

select empno,ename
from emp;

 

rowtype 타입으로 변수선언

declare
    -- rowtype 타입
    -- 테이블에 컬럼명을 변수로 사용하자
    remp emp%rowtype;
    
begin
    select * into remp
    from emp
    where ename = 'SCOTT';
    
    dbms_output.put_line(remp.empno || ' : ' || remp.ename);
    dbms_output.put_line(remp.job || ' : ' || remp.sal);
    dbms_output.put_line(remp.mgr || ' : ' || remp.hiredate);
    dbms_output.put_line(remp.comm || ' : ' || remp.deptno);
    
end;
/

-- 부서테이블 20번 부서정보를 rowtype를 적용하여 출력하세요


select * from dept;

declare
    rdept dept%rowtype;
    
begin
    select * into rdept
    from dept
    where deptno = 20;
    
    dbms_output.put_line(rdept.deptno || ' : ' || rdept.dname || ' : ' || rdept.loc);
  
end;
/

 

 

🍀 조건문

 

if 문

-- 조건문
-- 하나의 레코드만 조회되게 만들어야 한다

-- pl/sql 구분의 if문은 3가지
-- if문
-- if else 문
-- 다중 if문



declare
    vempno number(4);
    vename varchar2(20);
    vdeptno emp.deptno%type;
    vdname varchar2(10);
begin
    select empno, ename, deptno into vempno, vename, vdeptno
    from emp
    where empno = '7788';
    
    if(vdeptno = 10) then
    vdname := 'AAA';
    end if;
    
    if(vdeptno = 10) then
    vdname := 'BBB';
    end if;
    
    if(vdeptno = 10) then
    vdname := 'CCC';
    end if;
    
    if(vdeptno = 10) then
    vdname := 'DDD';
    end if;
    
    dbms_output.put_line(vempno || ' : ' || vename);
    dbms_output.put_line(vdeptno || ' : ' || vename);
end;
/
-- 사원의 연봉을 출력하는 프로그램

declare
    vemp emp%rowtype;
    annsal number(7,2);
    
begin
   select * into vemp
   from emp
   where ename = 'SCOTT';
   
   if (vemp.comm is null) then
   vemp.comm := 0;
   end if;
   
   annsal := vemp.sal * 12 + vemp.comm;
   
   dbms_output.put_line('사 번' || ' : ' || '이 름' || ' : ' || '연 봉');
   dbms_output.put_line(vemp.empno || ' : ' || vemp.ename || ' : ' || annsal);
end;
/

 

if else문, 다중 if문

-- if else 문

declare
    vemp emp%rowtype;
    annsal number(7,2);
    
begin
   select * into vemp
   from emp
   where ename = 'SCOTT';
   
   if(vemp.comm is null) then
   annsal := vemp.sal * 12;
   else 
   annsal := vemp.sal * 12 + vemp.comm;
   end if;
   
   dbms_output.put_line('사 번' || ' : ' || '이 름' || ' : ' || '연 봉');
   dbms_output.put_line(vemp.empno || ' : ' || vemp.ename || ' : ' || annsal);
end;
/



-- 다중 if문

declare
    vempno number(4);
    vename varchar2(20);
    vdeptno emp.deptno%type;
    vdname varchar2(10);
begin
    select empno, ename, deptno into vempno, vename, vdeptno
    from emp
    where empno = '7788';
    
    if(vdeptno = 10) then
    vdname := 'AAA';
    elsif(vdeptno = 20) then
    vdname := 'BBB';
    elsif(vdeptno = 30) then
    vdname := 'CCC';
    elsif(vdeptno = 40) then
    vdname := 'DDD';
    end if;
    
    dbms_output.put_line(vempno || ' : ' || vename);
    dbms_output.put_line(vdeptno || ' : ' || vename);
end;
/

 

제약조건 삭제하기

-- 제약조건 삭제하기
alter table emp07
drop primary key;

alter table emp07
drop constraint emp07_empno_pk;

 

foreign key : 두개의 테이블을 사용하여 값을 참조하고 제한 하는 조건

-- foreign key (fk)
-- 자식테이블이 부모테이블의 정보를 참조
-- 부모테이블이 먼저 존재
-- 나중에 생성된 테이블이 자식테이블
-- 자식테이블에만 F.K 조건을 설정
-- 부모쪽 해당 컬럼은 primary key여야 한다.

-- fk references 라고 써야한다

-- 컬럼레벨 방식
create table emp08 (
empno number(4) constraint emp08_empno_pk primary key,
ename varchar2(10) constraint emp08_ename_nn not null,
job varchar2(15),
deptno number(2) constraint emp08_deptno_fk references dept(deptno)
);

insert into emp08
values (1111, 'hong', 'sales', 10);

insert into emp08
values (2222, 'kim', 'sales', 50);

select * from emp08;

-- scott 계정은 맥에서 직접 터미널을 이용해 만들었기 때문인지 테이블 정보들이 조금씩 다름
-- dept 테이블 deptno에 pk 설정이 되지 않아 이 구문을 통해 직접 부여
alter table dept
add primary key(deptno);


-- 테이블 레벨 방식
create table emp09 (
empno number(4) constraint emp09_empno_pk primary key,
ename varchar2(10) constraint emp09_ename_nn not null,
job varchar2(15),
deptno number(2),

-- 나의 정보()에 대해 제약조건을 걸겠다 라고 써줘야 한다
constraint emp09_deptno_fk foreign key(deptno) references dept(deptno)
);

-- 테이블이 생성된 후의 레퍼런스(참조) 
-- alter table emp09
-- add constraint emp09_deptno_fk foreign key(deptno) references dept(deptno)

실제 프로그램을 짜면 관리해야 하는 데이터가 많은데

여러개의 테이블 중 서로 관계를 맺는 테이블 존재

foreign key 제약조건 성립한 테이블끼리는 조인 조건.

 

🍀 view

-- view (select 구문이다)
-- 특정 조건에 따라 필터링된 가상 테이블
-- 데이터 보호와 보안을 위해 만들어짐
-- 복잡한 쿼리문의 사용을 단순화할 수 있다
-- crud 가능

-- 뷰 테이블 만드는 형식
create [or replace] view 뷰 이름[(값1, 값2, ... )]
as
서브쿼리문
[with check option]
[with read only]

-- 서브쿼리문
-- select (select)
-- from (select)
-- where (select)

 

뷰 테이블 만들기에 앞서 원본 테이블이 있어야 함.

-- 원본테이블 생성
create table dept_copy 
as 
select * from dept;

create table emp_copy
as
select * from emp;

select * from emp_copy;

 

 

뷰 테이블 만들기

-- 뷰 테이블 작성
create view emp_view30
as 
select * from emp_copy
where deptno = 30;

select * from emp_view30;

 

테이블을 만드는 것도 권한, (오라클에서 자체적으로 줌)

뷰를 만드는 권한 부여를 해야 함. (system 계정에서 객체 권한 주기)

-- system 계정에서

grant create view
to scott;

 

(다시 scott계정에서)

뷰 테이블 생성, 삭제, 수정

-- USER_VIEWS
-- 딕셔너리 테이블
-- 구조 보기
desc user_views;

-- 아래 text를 통해 select 구문을 확인할 수 있음
select view_name, text 
from user_views;

-- 내꺼 + 위임 받은 view 까지 조회
select view_name, text 
from all_views;


create view emp_dept_sal
as
select ename, sal, e.deptno, dname, grade
from emp e inner join dept d
on e.deptno = d.deptno
inner join salgrade s
on e.sal between s.losal and s.hisal;

select * from emp_dept_sal;

-- 뷰 삭제
drop view emp_dept_sal;

-- 뷰 수정
create or replace view emp_view30
as 
select empno, ename, sal, hiredate, deptno
from emp_copy
where deptno = 30;

select * from emp_view30;

 

 

제약이 있는 뷰 테이블

-- [with check option]
-- 특정 컬럼 정보 수정 불가

-- [with read only]
-- 전체 컬럼 수정 불가

-- 특정 컬럼 정보 수정 불가 뷰
create or replace view view_chk30
as
select empno, ename, sal, comm, deptno
from emp_copy
where deptno = 30 with check option;

select * from view_chk30;

update view_chk30
set deptno = 20 -- 뷰의 WITH CHECK OPTION의 조건에 위배 됩니다
where deptno = 30; 


-- 읽기 전용 뷰 (전체 컬럼 수정 불가)
create or replace view view_read20
as
select empno, ename, sal, comm, deptno
from emp_copy
where deptno = 20 with read only;

select * from view_read20;

update view_read20 -- 읽기 전용 뷰에서는 DML 작업을 수행할 수 없습니다.
set sal = sal * 1.1
where sal >= 3000;

 

 

뷰 테이블 별칭 부여

-- 별칭 부여 가능 (한글도 가능, 하지만 권하지 않음)
-- 가능하다면 별칭을 안쓰는 것이 좋다
create or replace view view_read10 (사원번호, 사원명, 급여, 부서번호)
as
select empno, ename, sal, deptno
from emp_copy
where deptno = 10 with read only;

select * from view_read10;

select * from view_read10
where ename = 'KING'; -- 오류가 생긴다

-- 뷰테이블을 만들 때 별칭을 부여했다면 조회할 때도 별칭을 사용해야 한다.
select * from view_read10
where 사원명 = 'KING';

 

 

뷰 테이블 활용

-- 뷰 테이블을 활용한 TOP-N 구하기
-- rownum(의사컬럼) : 조회 시 레코드 순서대로 1번 부터 번호 부여
-- 오라클 시스템에서 제공해주는 컬럼, 테이블에는 없지만 제공 -> 의사컬럼
-- 아무 테이블이나 사용 가능
-- rownum은 order by절보다 먼저 실행된다, 조건절에 사용 시 반드시 1을 포함한 조건식을 만들어야 한다.

select rownum, empno, ename, sal, deptno
from emp
where rownum >= 1 and rownum <= 2;

-- rownum을 쓰는 순간 * 사용 불가
-- 전체 컬럼 조회 시 테이블에 별칭을 준다
select rownum, e.*
from emp e;


-- 입사일이 가장 빠른 사람 5명

select rownum, e.*
from emp e
order by hiredate asc;
-- order by를 쓰면 rownum 이 섞여버린다
-- order by가 쿼리문의 가장 마지막에 실행됨.

-- 원하는 실행방법이 아님
select rownum, e.*
from emp e
where rownum >= 1 and rownum <= 5
order by hiredate asc;

-- 원하는 형태로 출력을 위해 뷰 테이블 만들어서 출력
create or replace view view_hire
as
select * from emp
order by hiredate asc;

select rownum, h.*
from view_hire h;

select rownum, h.*
from view_hire h 
where rownum between 1 and 5;


-- 입사일이 빠른 사람 2번째 ~ 6번째
-- rownum을 간접적으로 사용하기
select rownum, h.*
from view_hire h 
where rownum > 1 and rownum <= 6;
-- 실행 X


delete from emp
where ename = 'a';


-- 인라인 뷰
-- 일회성 가상 테이블
-- 메모리의 부화를 주지 않음 -> 효율성이 높아진다

select rownum, h.*
from (
select empno, ename, hiredate
from emp
order by hiredate
) h
where rownum between 1 and 5;


-- 입사일이 빠른 사람 2번째 ~ 6번째
-- rownum에 별칭을 부여함으로서 고정시킬 수 있음.
select rownum rm, h.*
from (
select empno, ename, hiredate
from emp
order by hiredate
) h;

select rm, h2.*
from (
        select rownum rm, h.*
        from (
            select empno, ename, hiredate
            from emp
            order by hiredate
        ) h
      ) h2
where rm between 2 and 6;

→ 게시판 만들기할때 사용

 

 


 

오후에 자바스크립트를 제이쿼리로 바꾸기 시험을 본다.

그 전에 참고할 내용 정리!

 

$("셀렉터").html()
셀렉터 태그 내에 존재하는 자식태그을 통째로 읽어올때 사용되는 함수

※ 태그 동적추가할때 주로 사용되는 함수

$("셀렉터").text()
셀렉터 태그 내에 존재하는 자식태그들 중에 html태그는 모두 제외 한 채 문자열만 출력하고자 할때 사용되는 함수

※ html태그까지 모두 문자로 인식시켜주는 함수

출처:

 

jQuery 3강 - html() vs text() 함수 차이점 알아보기 + val() 함수를 이용한 input 태그의 값 확인 추가

jQuery에서 지원되는 함수만으로 간단하게 태그값들을 확인 할수 있습니다.그리고 반대로 원하는 값을 태그값에 적용 또한 가능합니다. html()함수와 text() 함수 그리고 val() 함수에 대하여 포스팅

hellogk.tistory.com

[IT Code Storage:티스토리]

내가 설치한 오라클 버전 : 21c Express Edition

 

컴퓨터 재시작 했을 때 터미널에서

💡 colima start --memory 4 --arch x86_64

💡 docker start oracle

 

계정

  • system / pass
  • scott / tiger
  • oe / oe

 

시험일정 )

수 → 자바스크립트 [퀴즈만들기] 제이쿼리로 바꾸기

금 → 오라클


 

🍀 DDL

-- 테이블 만드는 방식 알아보기
-- DDL (data definition language)
-- creat : 객체 생성
-- alter : 객체 수정
-- drop : 객체 삭제
-- truncate : 테이블을 초기화 (전체 데이터 삭제)

-- create table 테이블명 (
-- 컬럼명1 타입, 
-- 컬럼명2 타입,
-- 컬럼명3 타입,
-- );

-- 컬럼이름을 만든 후 타입에 사용
-- 숫자 : number(4), number(7,2)
-- 문자 : char(10) : 고정형, varchar2(10) : 가변형
-- 문자를 다룰 때는 가변형을 주로 사용한다
-- 날짜 : date, timestamp
-- 큰 데이터를 담을 때 : lob, blob 

-- 테이블명, 객체이름
-- 공백, 특수문자, 예약어 안됨

 

테이블을 만드는 방식 두 가지

  1. 직접 만들기
  2. 서브쿼리문을 사용한 테이블 생성

 

서브쿼리문을 사용해 테이블 만들기

-- 서브쿼리문을 사용한 테이블 생성 (테이블 복사)
-- 테스트용, 백업용으로 주로 만든다
create table emp02
as 
select * from emp;

desc emp02;

select * from emp02;

create table emp03
as
select empno, ename from emp;


create table emp04
as
select * from emp
where deptno = 30;

desc emp04;

select * from emp04;

-- 구조만 복사 
create table emp05
as
select * from emp
where 1 = 0;

select * from emp05;

 

 

객체 수정

-- alter : 객체 수정 
-- 테이블을 대상으로 컬럼을 수정 (add, modify, drop)

desc emp01;

alter table emp01 
add (job varchar2(9));

desc emp01;



-- modify
-- 해당 컬럼의 크기나 타입 수정
-- 기존 데이터에 문제가 되지 않는 선에서 수정해야 한다

alter table emp01
modify (job varchar(30));

desc emp01;

 

 

객체 삭제

-- 삭제
alter table emp01
drop column job;

desc emp01;

select * from tab;

drop table emp01;

삭제를 해도 임시로 휴지통에 보관을 해서 다시 사용할 수 있다!

 

🗑 휴지통에서 데이터 가져오기, 비우기

-- 휴지통 정보를 확인
show recyclebin;

-- 휴지통에서 원래 위치로 가져다 놓기
flashback table emp01
to before drop;

-- 휴지통 비우기
-- 이걸하면 원복할 방법이 없다
purge recyclebin;

 

🗑  휴지통에 넣지 않고 데이터 완전 삭제

-- 데이터 완전 삭제
select * from emp02;

truncate table emp02;

 

 

🍀 딕셔너리 (데이터 사전)

-- 이런 모든 작업을 다 저장, 관리해주는 오라클DB
-- 딕셔너리 (데이터 사전)
-- 오라클DB가 자체적으로 관리하는 테이블. 
-- 사용자가 직접 접근하지 못한다
-- 권한 별 접근 제한
-- XXX : 대상 객체를 의미 (table, index, veiw ...)
-- DBA_XXX (DBA 계정만) (system 계정도 DBA)
-- ALL_XXX (해당 계정의 객체 + 위임받은 정보)
-- USER_XXX (해당 계정의 객체)

select * from dict
where table_name like '%USER_TABLE%';

desc user_tables;

select table_name
from user_tables;

desc all_tables;

-- 위임받은 테이블 조회
select owner, table_name
from all_tables;

 

 

🍀 DML

-- DML (Data Manipulation Language)
-- 테이블에 데이터 조작
-- insert : 데이터 삽입
-- update : 데이터 수정
-- delete : 데이터 삭제

 

insert : 데이터 삽입

-- insert

-- 1. 컬럼의 개수가 값의 개수와 일치해야 한다
-- 2. 값의 타입도 일치해야 한다. 
insert into 테이블명 (컬럼명1, 컬럼명2, 컬럼명3, ... )
values (값1, 값2, 값3, ... )

desc dept01;

insert into dept01 (deptno, dname, loc) -- 자동형변환
values (10, 'sales' , 'inchon');

-- insert into dept01 (deptno, dname, loc) 
-- values ('aaa', 'sales' , 'inchon'); -- 자동형변환 불가

insert into dept01 (deptno, dname, loc) -- 자동형변환
values (10, 'sales' , 300); -- 숫자를 문자로 묶어도 문제가 되지 않아 자동형변환이 일어남

insert into dept01 (deptno, dname) -- 묵시적 null 삽입
values (20, 'sales');

insert into dept01 (deptno, dname, loc) -- 명시적 null 삽입
values (10, 'sales' , null);

insert into dept01 -- 컬럼을 생략하면 반드시 모든 컬럼에 값을 정의해야 한다
values (30, 'sales' , 'seoul'); 

select * from dept01;

오 이거 이제 보니 어제 oe 계정 만들면서 빡세게 했던거다!

역시 프로그래밍은 해매도 길이다 !

 

update : 데이터 수정

-- update 

-- update 테이블명
set 컬럼명1 = 값1, 컬럼명2 = 값2, 컬럼명3 = 값3, ...
[where 조건식];

drop table emp01;
create table emp01
as 
select * from emp;

update emp01
set deptno = 30;

update emp01
set empno = 1111, job = 'SALESMAN';

update emp01
set sal = sal * 1.1
where sal >= 3000;

select * from emp01;

-- 83년에 입사한 사원을 오늘 날짜로 수정
update emp01
set hiredate = sysdate
where substr(hiredate,1,2) = '83';

select * from emp01;

select ename, hiredate
from emp
where substr(hiredate,1,2) = '83';

 

delete : 데이터 삭제

-- delete
delete from 테이블명
[where 조건식]

delete from dept01
where deptno = 20;

select * from dept01;

 

 

🍀 트랜잭션

DML를 이용해 작업한 후에는 트랜잭션를 이용해 테이블에 반영하는 작업을 해줘야 한다. 그렇지 않으면 반영되지 않는다.

-- DML를 이용해 작업한 후에는 트랜잭션를 이용해 테이블에 반영하는 작업을 해줘야 한다.

-- 트랜잭션
-- TCL
-- commit : 해당테이블에 작업한 내용을 반영

-- rollback : 해당테이블에 작업한 내용을 반영하지 않는다. (작업 이전 상태로 원복)
-- rollback을 하면 이전 commit 위치로 돌아간다.

drop table dept01; 

create table dept01
as
select * from dept;

delete from dept01;

commit;

delete from dept01;

rollback;

select * from dept01;

-- delete (tx 가능), truncate (tx 불가)

 

commit 을 해야 실질적으로 반영된다.

 

 

테이블 생성 시 5대 제약조건

-- 5대 제약조건 : 무결성 데이터 처리 
-- 무결성 -> 원하지 않는 데이터
-- 컬럼의 값을 제약
-- not null : null를 허용하지 않는다.
-- unique : 중복된 값을 허용하지 않는다.
-- primary key : not null + unique
-- check : 값의 범위를 제한
-- foreign key : 두개의 테이블을 사용하여 값을 참조하고 제한 하는 조건


-- 제약조건을 주는 방식 3가지
-- 컬럼레벨 방식 : 컬럼을 정의하면서 제약조건을 정의하는 방식
-- 테이블 레벨 방식 : 컬럼의 정의와 제약조건 정의를 따로 분리하는 방식
--                1. 테이블 안에서 제약 조건을 분리하는 방식
--                2. 테이블 밖으로 제약 조건을 분리하는 방식



desc user_constraints;

select CONSTRAINT_NAME,CONSTRAINT_TYPE,TABLE_NAME
from user_constraints;

p : pk
r : fk
u : uk
c : ck,not null  

select CONSTRAINT_NAME,CONSTRAINT_TYPE,TABLE_NAME
from user_constraints;

select *
from user_cons_columns;

 

not null , unique

-- not null 과 unique
drop table emp01;

create table emp01(
    empno number(4) not null,
    ename varchar2(10) not null,
    job varchar2(10)
);

insert into emp01 (empno,ename,job)
values (1111,'hong','SALES');

select * from emp01;

drop table emp02;
create table emp02(
    empno number(4) unique not null,
    ename varchar2(10) not null,
    job varchar2(10)
);

insert into emp02
values (1111,'hong','sales');

insert into emp02
values (1111,'kim','dev'); -- 같은 값 중복 

insert into emp02
values (null,'park','dev'); -- null 삽입 불가

insert into emp02
values (null,'cho','dev');

select * from emp02;

 

primary key

-- primary key

drop table emp03;

create table emp03 (
empno number(4) primary key,
ename varchar2(10) not null,
job varchar2(10)
)

insert into emp03
values (1111, 'hong', 'sales');

insert into emp03
values (null, 'hong', 'sales'); -- null을 삽입할 수 없다

select * from emp03;

 

check

-- check
drop table emp04;

create table emp04 (
empno number(4) primary key,
ename varchar2(10) not null,
sal number(7,2) check(sal between 500 and 5000),
gender varchar2(2) check(gender in ('M','F'))
);


insert into emp04
values (1111, 'hong', 1000, 'F');

insert into emp04
values (2222, 'kim', 100, 'F'); -- 체크 제약조건 위배

insert into emp04
values (3333, 'kang', 1000, 'A'); -- 체크 제약조건 위배

select * from emp04;

 

제약조건명 지정

-- 제약조건명을 직접 지정할 수도 있다.
-- 제약조건명은 유니크해야 한다.
drop table emp05;

create table emp05 (
empno number(4) constraint emp05_empno_pk primary key,
ename varchar2(10) constraint emp05_ename_nn not null,
sal number(7,2) constraint emp05_sal_ck check(sal between 2000 and 5000),
gender varchar2(2) constraint emp05_gender_ck check(gender in ('M','F'))
);

insert into emp05
values (1111, 'kang', 2000, 'F'); 

insert into emp05
values (1111, 'kim', 2000, 'F');  -- 체크 제약조건 위배

insert into emp05
values (2222, 'hong', 100, 'F'); -- 체크 제약조건 위배

insert into emp05
values (2222, 'hong', 100, 'A'); -- 체크 제약조건 위배

select * from emp05;



-- 값을 디폴트하게 제어하는 방식

drop table dept01;

create table dept01 (
deptno number(2) primary key,
dname varchar2(10) not null,
loc varchar2(10) default 'SEOUL'
);

insert into dept01 (deptno, dname)
values (10, 'DEV');

insert into dept01 (deptno, dname, loc)
values (20, 'DEV', 'BUSAN');

select * from dept01;

위에는 다 컬럼레벨 방식으로 제약조건을 줬다.

 

 

제약조건을 주는 방식 - 테이블 레벨

-- 테이블 레벨 방식의 재약 조건 설정하기
-- not null 제약조건은 컬럼 레벨 방식만 가능
create table emp06 (
empno number(4),
ename varchar2(10) constraint emp06_ename_nn not null,
job varchar2(10),
deptno number(2),

constraint emp06_empno_pk primary key (empno),
constraint emp06_job_uk unique(job)
);

select CONSTRAINT_NAME,CONSTRAINT_TYPE,TABLE_NAME
from user_constraints
where table_name = 'EMP06';

select *
from user_cons_columns
where table_name = 'EMP06';



-- 외부에서 제약조건을 주는 방식

-- 테이블 생성
create table emp07 (
empno number(4),
ename varchar2(10),
job varchar2(10),
deptno number(2)
);

-- 테이블 생성 후 제약조건을 분리해서 주기
-- alter table 테이블명 
-- add 제약조건명 제약조건(컬럼명)

alter table emp07
add constraint emp07_empno_pk primary key(empno);

alter table emp07
add constraint emp07_job_uk unique(job);

-- null 값을 줄 수는 없지만 null로 상태를 변경할 수 있다
alter table emp07
modify ename constraint emp07_ename_nn not null;

select CONSTRAINT_NAME,CONSTRAINT_TYPE,TABLE_NAME
from user_constraints
where table_name = 'EMP07';

select *
from user_cons_columns
where table_name = 'EMP07';

+ Recent posts