728x90

파일첨부를 구현하는 중 사용자가 첨부하는 파일명의 중복을 없애기 위해 탐색 중 알게된 개념을 정리한다.

UUID(Universally Unique Identifier)란?

  • 위키백과 : 범용 고유 식별자(汎用固有識別子, 영어: universally unique identifier, UUID)는 소프트웨어 구축에 쓰이는 식별자 표준
  • 고유 식별자로, 주로 중복을 제거하기 위해 사용한다.
  • 만약 서로 다른 사용자가 다른 사진을 첨부했는데 서버에 저장되는 파일명이 같다면? 이런 상황을 피하기 위해 UUID를 사용할 수 있다.

 

구현 방법

String id = UUID.randomUUID().toString();
  • 생성 시 UUID 형태이므로 toString을 사용해준다.
728x90

게시판 댓글관리 구현 중 삭제된 게시글(tb_board.delete_yn = 'Y')에 달렸던 댓글은 댓글관리에서 볼 수 없게 하기위한 처리를 진행하다가 조인이 불가피하여 사용하였다. (조인은 속도를 늦추니 불가피한 경우에만 사용하면 좋다고 기억)

그 과정에서 탐색한 조인 방법을 정리한다.

1. 테이블

CREATE TABLE `tb_board` (
  `id` int NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  `content` text NOT NULL,
  `writer_id` int NOT NULL,
  `writer` varchar(20) NOT NULL,
  `delete_yn` varchar(1) DEFAULT 'N',
  `create_date` datetime DEFAULT NULL,
  `views` int DEFAULT '0',
  `image` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `writer_id` (`writer_id`),
  CONSTRAINT `tb_board_ibfk_1` FOREIGN KEY (`writer_id`) REFERENCES `tb_userinfo` (`id`) ON DELETE CASCADE
)
CREATE TABLE `tb_comment` (
  `id` int NOT NULL AUTO_INCREMENT,
  `board_id` int NOT NULL,
  `content` text NOT NULL,
  `writer_id` int NOT NULL,
  `writer` varchar(20) NOT NULL,
  `create_date` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `board_id` (`board_id`),
  KEY `writer_id` (`writer_id`),
  CONSTRAINT `tb_comment_ibfk_1` FOREIGN KEY (`board_id`) REFERENCES `tb_board` (`id`) ON DELETE CASCADE,
  CONSTRAINT `tb_comment_ibfk_2` FOREIGN KEY (`writer_id`) REFERENCES `tb_userinfo` (`id`) ON DELETE CASCADE
)

2. Inner Join 예시

select c.*
from board.tb_board b join board.tb_comment c 
	on b.delete_yn='y' and b.id = c.board_id and c.writer = 'rhkdals'
order by b.id;
  • select * from [ ] join [ ] on [조건]
  • select c.* : tb_comment 테이블의 컬럼만 모두 조회
728x90

체크박스에 체크하고 삭제하는 글관리 구현 중 전체 체크박스를 체크하는 기능을 구현한다.

 


1. html 코드

                <table class="table caption-top table-bordered table-hover">
                    <caption>List</caption>
                    <thead>
                        <tr>
                            <th class="text-center" width="50" scope="col">
                                <input type="checkbox" onclick="selectAll(this)">
                            </th>
                            <th class="text-center" width="50" scope="col">No</th>
                            <th class="text-center" width="950" scope="col">제목</th>
                            <th class="text-center" width="200" scope="col">작성일</th>
                            <th class="text-center" width="180" scope="col">작성자</th>
                        </tr>
                    </thead>

                    <tbody>
                        <tr th:each="board : ${boardList}">
                            <td class="mt-5 text-center" scope="row">
                                <div class="checkbox">
                                    <input type="checkbox" name="boardIdList" th:value="${board.id}">
                                </div>
                            </td>
                            <td class="mt-5 text-center" scope="row" th:text="${board.id}">1</td>
                            <td><a th:text="${board.title}" th:href="@{/board/post(boardId=${board.id})}"
                                    style="text-decoration:none; color:black;">제목</a></td>
                            <td class="text-center" th:text="${#dates.format(board.createDate, 'yyyy/MM/dd HH:mm')}">작성일
                            </td>
                            <td class="text-center" th:text="${board.writer}">작성자</td>
                        </tr>
                    </tbody>
                </table>
  • 체크박스에 onclick 이벤트를 달아준다.

2. 스크립트 코드

    <script>
        function selectAll(selectAll) {
            var checkboxs = document.querySelectorAll(['input[type="checkbox"]'])

            checkboxs.forEach((checkbox) => {
                checkbox.checked = selectAll.checked
            })
        }
    </script>
  • document.querySelectorAll : 모든 체크박스 쿼리를 가져옴
  • this로 체크박스를 받았기 때문에 this체크박스가 체크되면 모든 체크박스가 체크되도록 코드 작성

* 출처 : https://hianna.tistory.com/432

728x90

휴지통 삭제, 복원을 구현하는 방법으로 ajax 통신을 사용하기로 한다.

이 때 체크박스 체크된 게시글만 삭제, 복원 가능하도록 하려고한다.

 -> 리스트로 boardId를 서버로 보내서 처리하도록 한다!


1. Controller

    // 휴지통 게시글 복원
    @PatchMapping("/trash")
    @ResponseBody
    public void restoreBoards(@RequestParam(name = "boardIdList[]", required = false) List<String> boardIdList) {
        for(int i = 0; i < boardIdList.size(); i ++) {
            boardService.restore(Long.parseLong(boardIdList.get(i)));
        }
    }

    // 휴지통 게시글 영구 삭제
    @DeleteMapping("/trash")
    @ResponseBody
    public void clearBoards(@RequestParam(name = "boardIdList[]", required = false) List<String> boardIdList) {
        for(int i = 0; i < boardIdList.size(); i ++) {
            boardService.clear(Long.parseLong(boardIdList.get(i)));
        }
    }
  • @RequestParam(name = "boardIdList[]") : 배열을 List로 받을 것이기 때문에 변수 끝에 대괄호([])를 붙여준다.

2. View

            <!-- contents -->
            <form class="row g-3 justify-content-end">
                <table class="table caption-top table-bordered table-hover">
                    <caption>List</caption>
                    <thead>
                        <tr>
                            <th class="text-center" width="50" scope="col"></th>
                            <th class="text-center" width="50" scope="col">No</th>
                            <th class="text-center" width="950" scope="col">제목</th>
                            <th class="text-center" width="200" scope="col">작성일</th>
                            <th class="text-center" width="180" scope="col">작성자</th>
                        </tr>
                    </thead>

                    <tbody>
                        <tr th:each="board : ${boardList}">
                            <td class="mt-5 text-center" scope="row">
                                <div class="checkbox">
                                    <input type="checkbox" name="boardIdList" th:value="${board.id}">
                                </div>
                            </td>
                            <td class="mt-5 text-center" scope="row" th:text="${board.id}">1</td>
                            <td><a th:text="${board.title}" th:href="@{/board/post(boardId=${board.id})}"
                                    style="text-decoration:none; color:black;">제목</a></td>
                            <td class="text-center" th:text="${#dates.format(board.createDate, 'yyyy/MM/dd HH:mm')}">작성일
                            </td>
                            <td class="text-center" th:text="${board.writer}">작성자</td>
                        </tr>
                    </tbody>
                </table>
                <div class="nav justify-content-end">
                    <button type="submit" class="btn btn-primary me-2" onclick="restoreBoards()">복원하기</button>
                    <button type="submit" class="btn btn-danger" onclick="deleteBoards()">삭제하기</button>
                </div>
            </form>
  • form 태그안에 버튼을 생성하고 각 버튼의 onclick을 등록한다.

3. ajax(script코드)

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script th:inline="javascript">
        // 게시글 복원
        function restoreBoards() {
            var boardIdList = []

            $('input[name="boardIdList"]:checked').each(function (i) {
                boardIdList.push($(this).val());
            });

            if (!isEmptyArr(boardIdList)) {
                var param = { "boardIdList": boardIdList }

                $.ajax({
                    url: "/trash",
                    type: "PATCH",
                    data: param,
                    async: false,
                    success: function (response) {
                        alert('복원 됐습니다.')
                        location.reload()
                    },
                    error: function (response) {
                        alert('복원에 실패했습니다.')
                    }

                })
            } else {
                alert('복원할 게시글을 선택해주세요.')
            }
        }

        // 게시글 삭제
        function deleteBoards() {
            var boardIdList = []

            $('input[name="boardIdList"]:checked').each(function (i) {
                boardIdList.push($(this).val());
            });

            if (!isEmptyArr(boardIdList)) {
                var param = { "boardIdList": boardIdList }

                $.ajax({
                    url: "/trash",
                    type: "DELETE",
                    data: param,
                    async: false,
                    success: function (response) {
                        alert('영구 삭제 됐습니다.')
                        location.reload()
                    },
                    error: function (response) {
                        alert('영구 삭제 실패했습니다.')
                    }

                })
            } else {
                alert('삭제할 게시글을 선택해주세요.')
            }

        }

        // 빈배열 체크
        function isEmptyArr(arr) {
            if (Array.isArray(arr) && arr.length === 0) {
                return true;
            }

            return false;
        }
    </script>
  • var boardIdList = [] : 자바스크립트 배열 선언
  • $('input[name="boardIdList"]:checked').each(function (i) {  boardIdList.push($(this).val());  }); 
    • 체크박스에 체크된 개수만큼 each로 반복.
    • push를 통해 값을 배열에 초기화
  • isEmptyArr : 배열이 비었는지 체크

4. 결과

시연

 

+ 3번 스크립트 코드 수정!

만약 다중 게시글을 삭제하는데 팝업이 뜨지 않는다면? 당연하다.. 비동기적 통신으로 ajax를 실행해서 그렇다.

이를 해결하려면 동기적으로 ajax 통신을 사용해야하는데, async: false를 ajax 코드에 추가해주면된다.


* ajax 사용하기 : https://black-mint.tistory.com/35

 

[Spring Boot] Ajax(비동기) 통신으로 댓글 구현 (+ Jquery 사용법)

게시판 댓글을 구현하는 도중 비동기 호출에 대해 알게 됐고, 이를 이용하려면 Ajax를 활용해야 한다는 정보를 얻었다. 비동기란? 비동기의 반대인 동기적 통신의 경우 절차적으로 일을 차례로

black-mint.tistory.com

 

728x90
            var boardIdList = []

            $('input[name="boardIdList"]:checked').each(function (i) {
                boardIdList.push($(this).val());
            });
  • 이름이 boardIdList인 input태그의 체크된 값을 가져옴.
  • each로 반복하여 체크 개수만큼 push

* 출처 https://hanke-r.tistory.com/24

 

JavaScript - 체크박스 다중선택 value값

체크박스 다중선택 value값 가져오기 $("input[name=tblChk]:checked").each(function(){ var test = $(this).val(); console.log("체크된 값 : " + test); }); 체크박스 다중선택 value값 배열에 담기 var arTest..

hanke-r.tistory.com

 

728x90

서버에서 Json 형태로 프론트로 넘어오면 날짜 형식이 다음과 같이 변경돼서 날아온다.

"createDate""Jan 5, 2022, 4:25:48 PM"

원하는 날짜 형식으로 바꿔 보여주고 싶을 때 사용할 라이브러리

https://momentjs.com/

 

Moment.js | Home

Format Dates moment().format('MMMM Do YYYY, h:mm:ss a'); moment().format('dddd'); moment().format("MMM Do YY"); moment().format('YYYY [escaped] YYYY'); moment().format(); Relative Time moment("20111031", "YYYYMMDD").fromNow(); moment("20120620", "YYYYMMDD"

momentjs.com

사용법

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
  • 스크립트를 추가하고 사용하면된다.
moment(변수).format("YYYY-MM-DD HH:mm:ss")
  • 사용 문법

* 적용 프로젝트

https://black-mint.tistory.com/50

 

[Spring Boot] 댓글 기능 - REST API 규칙 적용

저번에 작성한 댓글 기능 구현 코드를 REST API 규칙에 맞게 수정하도록한다. * 이전 댓글 구현 글 https://black-mint.tistory.com/35 [Spring Boot] Ajax(비동기) 통신으로 댓글 구현 (+ Jquery 사용법) 게시판..

black-mint.tistory.com

 

728x90

저번에 작성한 댓글 기능 구현 코드를 REST API 규칙에 맞게 수정하도록한다.

 

* 이전 댓글 구현 글

https://black-mint.tistory.com/35

 

[Spring Boot] Ajax(비동기) 통신으로 댓글 구현 (+ Jquery 사용법)

게시판 댓글을 구현하는 도중 비동기 호출에 대해 알게 됐고, 이를 이용하려면 Ajax를 활용해야 한다는 정보를 얻었다. 비동기란? 비동기의 반대인 동기적 통신의 경우 절차적으로 일을 차례로

black-mint.tistory.com


1. REST(Representational State Transfer) API 란?

  • 네트워크 아키텍처 원리의 모음
  • 네트워크 아키텍처 : 자원을 정의하고 자원에 대한 주소를 지정하는 방법 전반을 의미
  • 예를 들어 학생

2. REST API 설계

  • URI는 정보의 자원을 표현
  • 자원에 대한 행위로 HTTP Method(GET, POST, PUT, PATCH, DELETE)로 표현
GET 데이터를 조회 (게시글 조회) GET /boards/1
게시글 중 1번 게시글을 조회
POST 데이터를 등록 (게시글 작성) POST /boards
게시글 등록
PATCH 데이터를 일부 수정 (게시글 수정) PATCH / boards/1
게시글 중 1번 게시글을 수정
PUT 데이터를 전체적으로 수정 PUT /boards/1
게시글 중 1번 게시글을 수정
DELETE 데이터를 삭제 DELETE /boards/1
게시글 중 1번 게시글을 삭제

3. REST API 규칙

  • 소문자로 작성하고 밑줄(_) 대신 하이픈(-)을 사용
  • 동사가 아닌 명사로 작성
  • 슬래시 구분자(/)는 계층 관계를 나타낼 때 사용하고 URI 마지막에 쓰지 않는다.
  • URI에 파일 확장자는 작성하지 않는다.

이 외 규칙이 많지만 이러한 2~3번 규칙을 잘 지켜서 만든 API를 RESTful API라고 한다.


4. 컨트롤러

@RequestMapping("/comments")
@RestController
public class CommentController {

    @Autowired
    private CommentService commentService;

    // 댓글 조회
    @GetMapping("/{boardId}")
    public List<Comment> getCommentList(@PathVariable(value = "boardId") Long boardId) throws Exception {
        List<Comment> comments = commentService.getCommentList(boardId);
        return comments;
    }

    // 댓글 작성
    @PostMapping("/{boardId}")
    public void commentWrite(@PathVariable(value = "boardId") Long boardId,
                             @RequestBody Comment comment,
                               Principal principal) throws Exception {
        String username = principal.getName();
        commentService.write(boardId, comment.getContent(), username);
    }

    // 댓글 수정
    @PatchMapping("/{commentId}")
    public void updateComment(@PathVariable(value = "commentId") Long commentId,
                              @RequestBody Comment comment) throws Exception {
        commentService.update(commentId, comment.getContent());
    }

    // 댓글 삭제
    @DeleteMapping("/{commentId}")
    public void deleteComment(@PathVariable(value = "commentId") Long commentId) throws Exception {
        commentService.delete(commentId);
    }
  • @RestController : 클래스 레벨에 선언하면 이전에 각 매핑마다 @ResponseBody 선언 했던 것을 하지 않아도 된다.
  • @ResponseBody : 해당 어노테이션이 선언된 매핑은 HTTP의 BODY에 자바 객체를 직접 반환한다.
  • @RequestBody : View에서 받아오는 JSON데이터를 파싱해준다. (변환할 데이터를 매핑 가능하도록 필드명 맞춰줘야함) 단, Content-Type이 multipart/form-data로 전달받을 때는 오류를 일으킨다. (주로 파일, 이미지를 전달받을 때)
  • @PathVariable : REST방식에서 주로 사용하며, @RequestParam과 유사. URI에 전달받을 변수를 지정

5. Ajax 통신 스크립트 코드

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
    <script th:inline="javascript">
        $(document).ready(function () {
            getComments()
        })

        function getComments() {
            var loginUsername = [[${ loginUser }]]
            var boardId = $('input[name=boardId]').val()
            var url = '/comments/' + boardId

            $.ajax({
                type: 'GET',
                url: url,
                success: function (response) {
                    var a = ''
                    var size = 0
                    $.each(response, function (key, value) {
                        size = size + 1;
                        a += '<hr /><div>'
                        a += '<input type="hidden" id="commentId" name="commentId" value="' + value.id + '">'
                        a += '<span id="writer" style="font-weight: bold;">' + value.writer + '</span>'
                        if (value.writer == loginUsername) {
                            a += '<ul name="commentChange" class="justify-content-end" style="display: inline;">'
                            a += '<li name="commentUpdate" type="button" style="display: inline; opacity: 0.7; font-size: small; margin-right: 5px" onclick="updateCommentForm(' + value.id + ')">수정</li>'
                            a += '<li name="commentDelete" type="button" style="display: inline; opacity: 0.7; font-size: small;" onclick="deleteComment(' + value.id + ')">삭제</li></ul>'
                        }
                        a += '<pre id="' + value.id + '" name="comment' + value.id + '" style="margin-bottom: 5px; font-size: large;">' + value.content + '</pre>'
                        a += '<p name="createDate' + value.id + '" style="margin-bottom: 5px; opacity: 0.5; font-size: small;">' + moment(value.createDate).format("YYYY-MM-DD HH:mm") + '</p></div>'
                    });
                    $("#count").html(size)
                    $("#comment").html(a)
                },
                error: function (response) {
                    console.log("getComments error : " + response)
                },
                complete: function () { }
            })
        }

        function insertComment() {
            var boardId = $('input[name=boardId]').val()
            var content = document.getElementById("content").value
            var param = {"content": content}
            var url = '/comments/' + boardId

            if (isEmpty(content) == true) {
                alert('댓글을 입력해주세요.')
                return false;
            } else {
                $.ajax({
                    contentType: 'application/json',
                    type: 'POST',
                    url: url,
                    data: JSON.stringify(param),
                    success: function (response) {
                        getComments()
                    },
                    error: function (response) {
                        console.log("insertComment error : " + response)
                    },
                })
            }
        }

        function updateCommentForm(id) {
            var commentId = id
            var content = document.getElementById(id).innerText

            $('ul[name=commentChange]').hide()
            $('pre[name=comment' + commentId + ']').contents().unwrap().wrap('<textarea id="newComment" class="form-control mt-2" name="updateContent" rows="4"></textarea>');
            $('p[name=createDate' + commentId + ']').contents().unwrap().wrap('<input name="update" type="button" class="me-2 mt-2 btn btn-primary" value="수정하기" onclick="updateComment(' + commentId + ')">');
            $('input[name=update]').after("<button class=\"me-2 mt-2 btn btn-primary\" onclick=\"getComments()\">취소</button>")
        }

        function updateComment(id) {
            var commentId = id
            var content = document.getElementById("newComment").value
            var param = {"content": content}
            var url = '/comments/' + commentId

            if (isEmpty(content) == true) {
                alert('댓글을 입력해주세요.')
                return false;
            } else {
                $.ajax({
                    contentType: 'application/json',
                    type: 'PATCH',
                    url: url,
                    data: JSON.stringify(param),
                    success: function (response) {
                        getComments()
                    },
                    error: function (response) {
                        console.log("updateComment error : " + response)
                    },
                    complete: function () { }
                })
            }
        }

        function deleteComment(id) {
            var commentId = id
            var url = '/comments/' + commentId

            if (confirm("정말 삭제하시겠습니까?")) {
                $.ajax({
                    type: 'DELETE',
                    url: url,
                    success: function (response) {
                        getComments()
                    },
                    error: function (response) {
                        console.log("deleteComment error : " + response)
                    },
                    complete: function () { }
                })
            } else {
                return;
            }
        }
        function isEmpty(strIn) {
            if (strIn === undefined) {
                return true;
            }
            else if (strIn == null) {
                return true;
            }
            else if (strIn == "") {
                return true;
            }
            else {
                return false;
            }
        }
    </script>
  • 이전 글과 바뀐 부분
    • Json으로 서버에 데이터를 보내주기 위해 contentType을 json으로 설정
    • url을 REST API 규칙에 맞춰 작성
    • data: json.stringify( ) : ajax 통신의 데이터 전달부분을 미리 만들어둔 json형식의 자바스크립트 변수를 서버로 전달
    • type을 REST API 규칙에 맞춰 작성
    • 날짜 포맷을 변경하기 위해 moment라이브러리 사용
    • https://black-mint.tistory.com/51
 

[JavaScript] 날짜 포맷 변경 라이브러리

서버에서 Json 형태로 프론트로 넘어오면 날짜 형식이 다음과 같이 변경돼서 날아온다. "createDate": "Jan 5, 2022, 4:25:48 PM" 원하는 날짜 형식으로 바꿔 보여주고 싶을 때 사용할 라이브러리 https://m

black-mint.tistory.com

 

* REST 관련 참고 

https://congsong.tistory.com/30?category=749196 

728x90

1. 자바스크립트 빈 문자열 검사 함수

function isEmpty(strIn)
{
    if (strIn === undefined)
    {
        return true;
    }
    else if(strIn == null)
    {
        return true;
    }
    else if(strIn == "")
    {
        return true;
    }
    else
    {
        return false;
    }
}

* 출처 : https://stackoverflow.com/questions/19592721/isempty-is-not-defined-error

 

isEmpty is not defined-error

I was getting an error as isEmpty is not defined .what i have to do .while alerting too it is not showing any alert. <!DOCTYPE html> <html> <head> ...

stackoverflow.com

2. 활용

        function insertComment() {
            var boardId = $('input[name=boardId]').val()
            var content = document.getElementById("content").value;

            if (isEmpty(content) == true) {
                alert('댓글을 입력해주세요.')
                return false;
            } else {
                $.ajax({
                    type: 'POST',
                    url: '/board/comment/write',
                    data: {
                        boardId: boardId,
                        content: content
                    },
                    success: function (response) {
                        getComments()
                        console.log("insert success")
                    },
                    error: function (response) {
                        console.log("insertComment error : " + response)
                    },
                })
            }
        }
  • 댓글 추가 ajax 코드
  • 댓글 내용 없이 작성버튼을 클릭하면 경고문을 띄우고 리턴.
728x90

1. 테이블

CREATE TABLE `tb_board` (
  `id` int NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  `content` text NOT NULL,
  `writer_id` int NOT NULL,
  `writer` varchar(20) NOT NULL,
  `delete_yn` varchar(1) DEFAULT 'N',
  `create_date` datetime DEFAULT NULL,
  `views` int DEFAULT '0',
  `image` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `writer_id` (`writer_id`),
  CONSTRAINT `tb_board_ibfk_1` FOREIGN KEY (`writer_id`) REFERENCES `tb_userinfo` (`id`) ON DELETE CASCADE
)
CREATE TABLE `tb_comment` (
  `id` int NOT NULL AUTO_INCREMENT,
  `board_id` int NOT NULL,
  `content` text NOT NULL,
  `writer_id` int NOT NULL,
  `writer` varchar(20) NOT NULL,
  `create_date` datetime NOT NULL,
  PRIMARY KEY (`id`)
)

2. 외래키(FK) 추가

ALTER TABLE board.tb_comment ADD FOREIGN KEY(board_id) REFERENCES board.tb_board(id);
  • tb_comment의 board_id컬럼이 tb_board 테이블의 id 값을 참조하도록 설정
  • ALTER TABLE 참조하는 테이블 ADD FOREIGN KEY(참조하는 컬럼명) REFERENCES 참조받는 테이블(참조받는 컬럼명);
ALTER TABLE board.tb_comment ADD FOREIGN KEY(board_id) REFERENCES board.tb_board(id) ON DELETE CASCADE;
  • 참조받는 테이블의 데이터가 삭제되면 참조하는 테이블의 데이터도 삭제하고 싶을 때 ON DELETE CASCADE를 맨 뒷 부분에 추가하면 된다.

3. 제약조건 확인

SELECT * FROM information_schema.TABLE_CONSTRAINTS WHERE TABLE_SCHEMA = 'board';
728x90
$('input[name=a]').after("<button onclick=\"getComments()\">취소</button>")
  • $('선택 태그').after("")

+ Recent posts