안녕하세요

프로그램 과정에서 막혔던 문제들에 대한 해결책 정리


페이지 목록

2011년 7월 25일 월요일

JAVA JFrame X button 클릭 시 이벤트 헨들

public void setDefaultCloseOperation(int operation)
Sets the operation that will happen by default when the user initiates a "close" on this frame. You must specify one of the following choices:
  • DO_NOTHING_ON_CLOSE (defined in WindowConstants): Don't do anything; require the program to handle the operation in the windowClosing method of a registered WindowListener object.
  • HIDE_ON_CLOSE (defined in WindowConstants): Automatically hide the frame after invoking any registeredWindowListener objects.
  • DISPOSE_ON_CLOSE (defined in WindowConstants): Automatically hide and dispose the frame after invoking any registered WindowListener objects.
  • EXIT_ON_CLOSE (defined in JFrame): Exit the application using the System exit method. Use this only in applications.
The value is set to HIDE_ON_CLOSE by default. DO_NOTHING_ON_CLOSE => 아무 것도 안한다. HIDE_ON_CLOSE => 프레임을 감춘다. DISPOSE_ON_CLOSE => 프레임을 감추고 버린다. (그 프레임만 종료) EXIT_ON_CLOSE => 프로그램 자체를 끈다 (모든 프레임을 종료) 이 상수를 쓸 시에는 JFrame. 을 앞에 붙여야 한다. JFrame의 상수이기 때문이다.

JTable 값 가져 오는 방법

getValueAt

public Object getValueAt(int row,
                         int column)
Returns the cell value at row and column.Note: The column is specified in the table view's display order, and not in the TableModel's column order. This is an important distinction because as the user rearranges the columns in the table, the column at a given index in the view will change. Meanwhile the user's actions never affect the model's column ordering.

Parameters:
row - the row whose value is to be queried
column - the column whose value is to be queried
Returns:
the Object at the specified cell

Container에 Table 삽입 방법

Adding a Table to a Container

Here is typical code for creating a scroll pane that serves as a container for a table:
JScrollPane scrollPane = new JScrollPane(table);
table.setFillsViewportHeight(true);
// ScrollPane에 테이블을 넣는 방법
The two lines in this snippet do the following:
  • The JScrollPane constructor is invoked with an argument that refers to the table object. This creates a scroll pane as a container for the table; the table is automatically added to the container.
  • JTable.setFillsViewportHeight is invoked to set the fillsViewportHeight property. When this property is true the table uses the entire height of the container, even if the table doesn't have enough rows to use the whole vertical space. This makes it easier to use the table as a drag-and-drop target.
The scroll pane automatically places the table header at the top of the viewport. The column names remain visible at the top of the viewing area when the table data is scrolled.
If you are using a table without a scroll pane, then you must get the table header component and place it yourself. For example:
container.setLayout(new BorderLayout());
container.add(table.getTableHeader(), BorderLayout.PAGE_START);
container.add(table, BorderLayout.CENTER);
//Container에 직접 table을 삽입하는 방법
출처: http://download.oracle.com/javase/tutorial/uiswing/components/table.html#data

JTable 열과 행 삽입 방법


DefaultTableModel model = new DefaultTableModel();
JTable table = new JTable(model);

// Create a couple of columns
model.addColumn("Col1");
model.addColumn("Col2");

// Append a row
model.addRow(new Object[]{"v1", "v2"});
// there are now 2 rows with 2 columns

// Append a row with fewer values than columns.
// The left-most fields in the new row are populated
// with the supplied values (left-to-right) and fields
// without values are set to null.
model.addRow(new Object[]{"v1"});
// there are now 3 rows with 2 columns

// Append a row with more values than columns.
// The extra values are ignored.
model.addRow(new Object[]{"v1", "v2", "v3"});
// there are now 4 rows with 2 columns
출처: http://www.exampledepot.com/egs/javax.swing.table/AppendRow.html

2011년 7월 22일 금요일

세션 제거하기

 시간을 체크한다.

 세션 종료의 세가지 이유
 1) 시간이 다 되어서 (타임 아웃)
 2) 개발자가 세션 객체에 Invalidate() 메소드를 실행
 3) App이 다운되는 경우( 문제가 생겨 다운되거나, 언디플로이(undeploy) 되는 경우)

쿠키(Cookie)

 쿠키는 Header 중 하나이다.
 Container에서 거의 모든 Cookie 관련 작업을 수행한다.

 Response 객체에 세션 Cookie 보내는 방법
 HttpSession session = request.getSession();

 Request 객체로부터 세션 ID 가져오기
 HttpSession session = request.getSession();

session.isNew() - 세션이 새로 만들어졌는지 아닌지 확인

 URL 재작성 => response.encodeURL( " blur blur ");

 쿠키 => URL 재작성

 정적인 페이지는 URL 재작성이 불가 하다.

컨테이너에서 클라이언트를 구분 하는 방법

 Client는 유일한 Session ID가 필요하다. 그리고 쿠키를 사용해서 Client와 Container는 이 Session ID를 공유한다.

속성(Attribute)란?

 3개의 Servlet API 객체 (ServletContext, HttpServletRequest 또는
ServletRequest),HttpSession 객체 중 하나에 설정해 놓는 객체(Binding)

ServletContext를 리턴 받는 두 가지 방법

 1) getServletConfig().getServletContext().getInitParameter();
 2) this.getServletContext().getInitParamete()
 1) 번의 경우 HTTPServlet 이나 GenericServlet을 상속 받지 않는다.

ServletConfig

 ServletConfig의 역할 => 초기화 Parameter에 접금
 ServletContext 리턴하는 메소드 제공 -> Context 정보 (Servlet 설
정 정보)를 가짐
 웹 App의 다른 Component 와 공유할 경우 => Request 객체를 통
해 보냄. -> 그리 좋은 방법은 아니다.

 

Get 과 Post

 HTTP 요청 Method는 doGet()을 실행할 지 doPost()를 실행할 지
결정
 Get과 Post의 차이점
 Post는 몸체가 있다!!!!!
 Get을 사용하면 브라우져의 주소 입력 창에 Parameter data가 노출
 (보안 문제)
 Get은 즐겨 찾기 추가 가능(Post 불가)
 사용 용도 => Get (뭔가를 가져올 때)
                     Post (처리할 data를 보낼 때 - Update)

 Idempotent => 동일 작업을 부작용 없이 계속 할 수 있는 것
 Get = Idempotent(멱등)  Post = Idempotent 가 아니다.
 Post 는 defalut 값이 아님

Servlet의 일생

 Container가 Servlet file을 찾아서 loading 할 때 -> Container가 시
작 할 때 이루어짐
 1) 클래스 찾기  2) 클래스 로딩
 이 두 작업은 Container 마다 차이가 있다.

 Servlet 초기화
생성자 - 객체 생성 Init() - Servlet 생성

 1) ServletConfig 객체
  Servlet 당 하나
  Servlet 배포시 설정 된 정보를 서블릿으로 넘겨주기 위하여
 (예) Database or EJB 참조
 ServletContext에 접근하기 위해서 이 객체 사용
 Parameter 값은 배포 서술자에서 설정가능
 2) ServletContext 객체
 웹 어플리케이션 당 하나의 ServletContext (이름 - AppContext)
 웹 어플리케이션의 파라미터 정보를 읽어 오기 위해 (Parameter
 정보는 DD 안에 있음)
 어플리케이션 용 게시판 => 여기에 메세지(Attribute)를 적어 놓으
 면 Application의 다른 녀석들이 읽을 수 있음
 서버 정보 파악 => Container 이름 및 Version 지원하는 API ver
 sion

ServletConfig = Servlet 당 하나
ServletContext = Web App 당 하나

Servlet 함수

init()
 호출 시점 => Servlet instance 생성 후
 목적 => Client 요청 처리 전에 Servlet 초기화
 재 정의 가능

service()
 호출 시점 => 최초 Client 요청을 받았을 때, Container는 새로운 스
                   레드 생성 or 스레드 풀에서 하나를 가지고 와서 서블
                   릿의 service 메소드 호출
 목적 => Client의 HTTP Method(Get, Post 등)를 참조하여 doGet(),
            doPost(), 또는 다른 메소드 호출을 판단
 재정의 불가

 doGet()
 or
 doPost()

 호출 시점 => service() 메소드가 Client의 HTTP Method(Get,Post)
       를 참조하여 doGet() or doPost() 호출
 목적 => 코딩을 하는 장소
 재정의 - 둘 중 하나는 반드시

Servlet 개발 5단계

 1) 사용자가 제일 먼저 볼 HTML 폼을 생성 => Test
 2) Controller servlet v1을 만듬
    v1 => HTML 폼이 Servlet을 호출하면 Parameter 값 출력
 3) Model class를 위한 Test Class를 만듬
 4) Servlet v2 => BeerExpert에게 맥주에 대한 조언을 구할 수
    있게 만듬
 5) JSP를 만들고 Servlet V3 => JSP에 요청 전달

MVC 패턴 (MVC Design Pattern)

 Model, View, Controller의 줄임말 (MVC)

 Model => 일반적인 자바 Class
                Business Data (장바구니 정보) , Business Method (장바
               구니 정보에 대한 조작 및 추출)
Controller => Request 객체에서 사용자가 입력한 정보를 뽑아내어,
                   Model에 대하여 어떤 작업을 해야 하는지 알아 냄.
                  (Model 정보 수정, 뷰(JSP)에게 넘겨줄 새로운 Model
                  형성)

View => JSP (실질적으로 브라우져에 띄워질 페이지)

Servlet 과 JSP의 차이점

 Servlet => 자바 안에 HTML을 넣는다.
 JSP => HTML 안에 자바 코드를 넣는다.

두 객체가 같다

 1) 두 레퍼런스가 똑같은 객체를 가리킴 (Reference Equality)
 2) 제목이 똑같은 서로 다른 객체 (Object Equality)

JAVA GUI Layout Manager(레이아웃 메니져)

1) Border Layout => North, South, West, East, Center 다섯 구역에 컴포넌트를 올릴 수 있다.
 Frame의 기본 Layout
2) Flow Layout => 워드 프로세스와 비슷한 방식을 사용한다. 크기는 요구대로 만들 수 있고, 순서대로 '왼쪽 맞춤' 형태로 제공된다. -> 수평 방향으로 들어가지 않을 시에 다음 '행'에 배치 된다.
 Panel 의 기본 Layout
3) Box Layout => 요청 크기대로 만들고 추가된 순서대로 배치한다. 주로 수직 방향으로 쌓을 시에 사용한다. (수평 방향도 가능하지만 잘 사용하지 않음)

JAVA GUI에 뭔가를 넣는 방법

 1) 프레임에 위젯 넣기
 2) 위젯에 2D 그래픽 그리기 => 그래픽 객체를 이용
 3) 그림 넣기

 위 3가지 방법이 있다.

JAVA GUI 중 클릭에 대하여

클릭 시 반응을 얻기 위해서 필요한 두가지

 1) 사용자 클릭시 호출 할 메소드(버튼 클릭 시 행동)
 2) 버튼 클릭을 알 수 있는 방법

 이 두 가지가 필요하다.

 Call Back Method => 이벤트가 일어 났을 때 호출 하는 메소드를 뜻하고 이 메소드가 이벤트 리스너에 그 이벤트가 일어났음을 알린다.
 Event Source => 사용자의 행동을 이벤트로 바꿔주는 객체이다.

2011년 7월 20일 수요일

JDBC select Example(JDBC select 예제)

/*
Database Programming with JDBC and Java, Second Edition
By George Reese
ISBN: 1-56592-616-1

Publisher: O'Reilly
*/

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

/**
 * Example 3.1.
 */
public class Select {
  public static void main(String args[]) {
    String url = "jdbc:msql://carthage.imaginary.com/ora";
    Connection con = null;

    try {
      String driver = "com.imaginary.sql.msql.MsqlDriver";

      Class.forName(driver).newInstance();
    catch (Exception e) {
      System.out.println("Failed to load mSQL driver.");
      return;
    }
    try {
      con = DriverManager.getConnection(url, "borg""");
      Statement select = con.createStatement();
      ResultSet result = select
          .executeQuery("SELECT test_id, test_val FROM test");

      System.out.println("Got results:");
      while (result.next()) { // process results one row at a time
        int key = result.getInt(1);
        String val = result.getString(2);

        System.out.println("key = " + key);
        System.out.println("val = " + val);
      }
    catch (Exception e) {
      e.printStackTrace();
    finally {
      if (con != null) {
        try {
          con.close();
        catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
  }
}


출처: http://www.java2s.com/Code/Java/Database-SQL-JDBC/JDBCselect.htm

JDBC getConnection

public static Connection getConnection() {

try {
Class.forName("org.gjt.mm.mysql.Driver"); // Class.forName("myDriver.ClassName");
// ?

} catch (java.lang.ClassNotFoundException e) {
System.err.print("ClassNotFoundException: ");
System.err.println(e.getMessage());
}

try {
con = DriverManager.getConnection(url, userid, password);

} catch (SQLException ex) {
System.err.println("SQLException: " + ex.getMessage());
}

return con;
}

JDBC Insert Example(JDBC insert 예제)


public static void insertEmployees()
 {
  Connection con = getConnection();
  
  String insertString1, insertString2, insertString3, insertString4;
  insertString1 = "insert into Employees values(6323, 'Hemanth')";
  insertString2 = "insert into Employees values(5768, 'Bob')";
  insertString3 = "insert into Employees values(1234, 'Shawn')";
  insertString4 = "insert into Employees values(5678, 'Michaels')";
  

  try {
   stmt = con.createStatement();
      stmt.executeUpdate(insertString1);
      stmt.executeUpdate(insertString2);
      stmt.executeUpdate(insertString3);
      stmt.executeUpdate(insertString4);

   stmt.close();
   con.close();

  } catch(SQLException ex) {
   System.err.println("SQLException: " + ex.getMessage());
  }

MySQL Data Type 정리

Integer Type
- TINYINT  128부터 127 까지의 정수형 타입,   부호가 없는 정수 0∼255까지 지원 
- SMALLINT  32768부터 32767 까지의 정수형 타입,  부호가 없는 정수 0∼65535까지 지원 
- MEDIUMINT  8388608부터 8388607 까지의 정수형 타입,   부호가 없는 정수 0∼16777215까지 지원 
- INT 또는 INTEGER   -2147483648부터 2147483647까지의 정수형 타입,
      부호 없는 정수 0∼4294967295까지 지원 
- BIGINT  9223372036854775808 부터 9223372036854775807 까지의 정수형 타입 
       부호 없는 정수 0∼18446744073709551615까지 지원 
- FLOAT(M,D) 단정도 부동 소수점 실수,   -3.402823466E+38 ∼ -1.175494351E-38  
  그리고 1.175494351E-38 ~ 3.402823466E+38까지  M은 숫자 전체의 길이, D는 소수점 자리수를 의미 
- DOUBLE(M,D) 2 배 정밀도를 가진 부동 소수점 실수,   -1.79769313486231517E+308 ∼ 2.22507385850720E+308


Stirng Type
-CHAR(m) 0~255까지 입력이 가능하며, 길이가 m길이만큼 고정 사이즈가 된다.
-
VARCHAR (m)0~255까지 입력은 가능하지만, 길이는 고정이 아닌 가변 사이즈이다.
-
BINARY(m) 이진 데이터를 바이트 지정한 만큼 고정 길이
-
VARBINARY(m) 이전 데이터를 바이트 지정한 만큼 넣는다. 가벼 길이
-TINYBLOB 이전 데이터를 최대 255자까지 입력이 가능하다
-
BLOB 최대 길이가 63535인 문자를 저장
-
TEXT 최대 길이가 63535인 문자를 저장
-MEDIUMBLOB 최대 길이가 16777215인 문자를 저장
-LONGBLOB 최대 입력이 4G 이진데이타, 최대 2^32 바이트
-
LONGTEXT 최대 입력이 4G 1바이트 문자열, 최대 2^32 자
/*  Point */
  - BLOB타입은 대소문자를 구분하고 TEXT타입은 대소문자를 구분하지 않는점이 틀림
  - MySQL 3.23.2이번 버전에서는 BLOB와 TEXT컬럼에는 인덱스를 만들수 없다
  - BLOB와 TEXT컬럼의 저장시에 문자열 됫부분의 공백이 제거되지 않는다.
  - BLOB와 TEXT컬럼은 DEFAULT를 지정할 수 없다.

Data Type
-DATE 날짜를 표현하는 유형 [YYYY-MM-DD], 1000-01-01 ∼ 9999-12-31까지 나타낼 수 있다
-DATETIME 날짜와 시간을 표현하는 유형 [YYYY-MM-DD HH:MM:SS],  1000-01-01 00:00:00 ∼ 9999-12-31 23:59:59
-TIMESTAMP 자동변경 컬럼 타입(4 Byte ),  1970-01-01 00:00:00부터 2037년 까지 표현
-TIME 시간을 표현하는 유형 [HH:MM:SS],   839:59:59 ∼ 833:59:59 까지 표현
-
YEAR 년도를 표현하는 유형[기본적으로 4자리로 사용],  1901년 ∼ 2155년

JDBC 사용방법


//STEP 1. Import required packages
import java.sql.*;

public class JDBCExample {
   // JDBC driver name and database URL
   static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";  
   static final String DB_URL = "jdbc:mysql://localhost/STUDENTS";

   //  Database credentials
   static final String USER = "username";
   static final String PASS = "password";
   
   public static void main(String[] args) {
   Connection conn = null;
   Statement stmt = null;
   try{
      //STEP 2: Register JDBC driver
      Class.forName("com.mysql.jdbc.Driver");

      //STEP 3: Open a connection
      System.out.println("Connecting to a selected database...");
      conn = DriverManager.getConnection(DB_URL, USER, PASS);
      System.out.println("Connected database successfully...");
      
      //STEP 4: Execute a query
      System.out.println("Creating table in given database...");
      stmt = conn.createStatement();
      
      String sql = "CREATE TABLE REGISTRATION " +
                   "(id INTEGER not NULL, " +
                   " first VARCHAR(255), " + 
                   " last VARCHAR(255), " + 
                   " age INTEGER, " + 
                   " PRIMARY KEY ( id ))"; 

      stmt.executeUpdate(sql);
      System.out.println("Created table in given database...");
   }catch(SQLException se){
      //Handle errors for JDBC
      se.printStackTrace();
   }catch(Exception e){
      //Handle errors for Class.forName
      e.printStackTrace();
   }finally{
      //finally block used to close resources
      try{
         if(stmt!=null)
            conn.close();
      }catch(SQLException se){
      }// do nothing
      try{
         if(conn!=null)
            conn.close();
      }catch(SQLException se){
         se.printStackTrace();
      }//end finally try
   }//end try
   System.out.println("Goodbye!");
}//end main
}//end JDBCExample

CHAR 와 VARCHAR의 차이점

CHAR는 고정형이고, VARCHAR는 가변형이라는 정도의 지식만 가지고 데이터베이스를 다루는 한국어권 사용자들을 위해, MySQL 레퍼런스 문서의 해당 내용을 번역해보았다. 

mysqlkorea에서도 본 내용을 번역하여 게시하고 있지만, 의역이 마음에 들지 않고 일부 삭제된 부분이 있어 다시 번역했다. mysqlkorea의 문서는 다음 링크를 통해 열람할 수 있다. 


아래 문서를 읽는 것 조차 귀찮은 분들을 위해 내용을 요약하고, 첨언하면 다음과 같다.
  • CHAR형은 고정형. 최대 길이는 255.
  • VARCHAR형은 가변형. 최대 길이는 255, MySQL 5.0.3 이후부터는 65,535까지 가능.
  • VARCHAR형은 255글자 이하에는 1바이트, 그 이상은 2바이트의 추가 공간을 필요로 한다.
  • 4.1 이후 버전부터는 CHAR(n), VARCHAR(n)에서 n은 바이트가 아니라, 글자 수를 의미. 즉, 캐릭터 셋의 영향을 받는다.
  • 문자열 뒤에 이어지는 공백들은 열의 형태/버전/SQL 모드에 따라 다르게 처리될 수 있다.
  • 임의의 바이트 배열을 저장할 때에는 BLOB를 선택하라.
  • CHAR / VARCHAR형을 비교하거나 정렬할 때에 뒤따르는 공백은 무시된다. 인덱스도 마찬가지.
  • VARCHAR형이 포함된 열을 삭제/갱신 하는 경우에는 테이블에 사용되지 않는 파편이 생길 수 있다. 이와 같은 가변 길이 행 형태의 테이블은 가끔 OPTIMIZE TABLE [tablename]을 통해 파편을 제거하여 디스크 용량 절약(테이블 스페이스를 쓰지 않는 경우)과 읽기 속도의 개선을 꾀할 수 있다.


10.4.1. CHAR 와 VARCHAR 형

CHAR와 VARCHAR 형은 유사하지만, 저장하고 읽어들이는 부분에는 다르다. MySQL 5.0.3 이후로는 최대 길이와 남은 공간의 보관 여부에 대해서도 달라졌다.
CHAR와 VARCHAR형은 보관하고자 하는 문자열의 최대 길이를 포함하여 선언하게 된다. 예를 들어, CHAR(30)은 30 글자까지 보관할 수 있다.
CHAR열의 길이는 테이블을 만들 때에 지정한 길이로 고정되며, 길이는 0부터 255까지 가능하다. CHAR값을 저장할 때는 문자열의 우측에 공백을 넣어 지정된 길이에 맞추게 된다. 값을 읽어들일 때에는 공백을 제거해서 읽는다.
VARCHAR열의 값은 가변 길이 문자열이다. 지정할 수 있는 길이는 0부터 255까지이며, MySQL 5.0.3 이후에는 0부터 65,535까지 지정할 수 있다. MySQL 5.0.3 이후 버전에서의 VARCHAR 유효 최대 길이는 최대 열 크기(최대 65,535바이트)와 캐릭터 셋의 사용에 영향을 받는다. 
CHAR형과는 다르게, VARCHAR형은 1바이트 혹은 2바이트의 값을 앞부분에 저장하며, 이는 값의 크기가 몇 바이트인지 나타낸다. 255글자 이하일 때는 1바이트, 그 이상이면 2바이트를 차지한다.
엄격한 SQL 모드(strict SQL mode)가 활성화되지 않은 상태에서, 열의 최대 길이를 초과하여 값을 저장하면, 값을 잘라서 보관하고 경고를 발생시킨다. 엄격한 SQL 모드를 활성화하면 공백이 아닌 문자열을 자를 때에 경고 대신 에러를 발생시키고 값을 추가하지 못하도록 할 수 있다. 자세한 내용은 다음 링크를 참고한다. Section 5.1.6, “Server SQL Modes”.
VARCHAR열에 해당 열의 길이를 초과하는 공백들은 SQL 모드에 관계없이 잘린 후 저장되며, 경고를 발생시킨다. CHAR열의 경우에는 마찬가지로 동작하지만, 경고가 발생하지 않는다.
VARCHAR 값은 저장될 때에 공백이 추가되지 않는다. 뒤따르는 공백에 대한 처리는 버전에 따라 다르다.  MySQL 5.0.3부터는 표준 SQL과의 호환성을 위해 뒤따르는 공백들을 제거하지 않고 보관하며, 읽어들일 때도 보존해준다. MySQL 5.0.3 이전에는 저장될 때에 뒤따르는 공백들은 제거되었고, 이는 값을 읽어들일 때에도 제거된 채로 읽힘을 의미한다.
MySQL 5.0.3 이전에 뒤따르는 공백들을 유지하기 위해서는 BLOB나 TEXT 형을 선택해야 했다. 또한, 암호화된 값이나 압축 기능을 통해 얻어진 임의의 바이트 형태의 값을 보관할 때에는 CHAR나 VARCHAR형 보다는 BLOB를 선택하는 것이, 데이터의 변형을 가져올 공백 제거에 따른 잠재적인 문제점으로부터 피할 수 있게 해준다.
다음 표는 문자열을 CHAR(4)와 VARCHAR(4) 열에 보관할 때의 결과를 통해 CHAR와 VARCHAR 형의 차이점을 보여준다. (모든 열은 latin1과 같은 1바이트 캐릭터 셋을 사용하는 것으로 가정한다.)
CHAR(4)필요한 저장소 크기 VARCHAR(4)필요한 저장소 크기
'''    '4 bytes''1 byte
'ab''ab  '4 bytes'ab'3 bytes
'abcd''abcd'4 bytes'abcd'5 bytes
'abcdefgh''abcd'4 bytes'abcd'5 bytes
마지막 열의 값은 엄격한 SQL 모드를 사용하지 않을 때만 적용된다. 만약 엄격한 SQL 모드로 MySQL이 동작한다면, 길이를 초과하는 값을 저장되지 않고 에러를 발생시키게 된다.
CHAR 열은 값을 읽을 때, 뒤의 공백을 제거하기 때문에, CHAR(4)와 VARCHAR(4)에 주어진 값과 읽었을 때 얻어진 값은 항상 같지는 않다. 다음은 이 차이를 보여주는 예제이다.
mysql> CREATE TABLE vc (v VARCHAR(4), c CHAR(4));
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO vc VALUES ('ab  ', 'ab  ');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT CONCAT('(', v, ')'), CONCAT('(', c, ')') FROM vc;
+---------------------+---------------------+
| CONCAT('(', v, ')') | CONCAT('(', c, ')') |
+---------------------+---------------------+
| (ab  )              | (ab)                |
+---------------------+---------------------+
1 row in set (0.06 sec)

CHAR와 VARCHAR 열에 쓰여진 값들을 정렬하거나 비교할 때에는 해당 열이 가지고 있는 캐릭터 셋 - 콜레이션(collation)의 영향을 받는다. 모든 MySQL의 콜레이션은 PADSPACE이다. 이는 MySQL의 CHAR와 VARCHAR 값들은 뒤따르는 공백의 영향 없이 비교될 수 있음을 의미한다.
mysql> CREATE TABLE names (myname CHAR(10), yourname VARCHAR(10));
Query OK, 0 rows affected (0.09 sec)

mysql> INSERT INTO names VALUES ('Monty ', 'Monty ');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT myname = 'Monty  ', yourname = 'Monty  ' FROM names;
+--------------------+----------------------+
| myname = 'Monty  ' | yourname = 'Monty  ' |
+--------------------+----------------------+
|                  1 |                    1 |
+--------------------+----------------------+
1 row in set (0.00 sec)
VARCHAR열에 값을 저장하기 전에 공백을 제거하는 MySQL 버전을 사용하고 있어도, SQL 모드의 활성 또는 비활성화되어 있어도 관계가 없으며, 모든 MySQL 버전에 해당한다. 
알림
MySQL 캐릭터 셋과 콜레이션은 다음을 참고한다. Section 9.1, “Character Set Support”.
이 같은 경우에 대해 뒤따르는 공백들은 제거되거나 비교 시에 무시하게 되므로, 해당 열이 유일한 인덱스(unique index)를 요구하는 경우에, 뒤따르는 공백의 수만 다르고 내용이 같은 문자열들을 입력하면 중복키 에러를 발생시킨다. 예를 들어, 해당 테이블이 'a'를 가지고 있는 상태에서 'a '를 저장하려 하면 중복키 에러가 발생한다.