programing

기존 SQLite 테이블에 외부 키를 추가하려면 어떻게 해야 합니까?

cafebook 2023. 10. 15. 17:54
반응형

기존 SQLite 테이블에 외부 키를 추가하려면 어떻게 해야 합니까?

저는 다음 표를 가지고 있습니다.

CREATE TABLE child( 
  id INTEGER PRIMARY KEY, 
  parent_id INTEGER, 
  description TEXT);

에 외국 키하려면 어떻게 합니까?parent_id 외부 키가 활성화되어 있다고 가정합니다.

대부분의 예제에서는 표를 작성한다고 가정합니다. 기존의 제약 조건에 제약 조건을 추가하려고 합니다.

그럴수는 없어요.

테이블에 외부 키를 추가하는 SQL-92 구문은 다음과 같습니다.

ALTER TABLE child ADD CONSTRAINT fk_child_parent
                  FOREIGN KEY (parent_id) 
                  REFERENCES parent(id);

SQLite는 다음을 지원하지 않습니다.ADD CONSTRAINTALTER TABLE명령(sqlite.org : SQLite에서 구현하지 않는 SQL 기능).

할 수 sqlite 3.6.1 에서 입니다.CREATE TABLE다음과 같이

CREATE TABLE child ( 
    id           INTEGER PRIMARY KEY, 
    parent_id    INTEGER, 
    description  TEXT,
    FOREIGN KEY (parent_id) REFERENCES parent(id)
);

안타깝게도 기존 데이터를 임시 테이블에 저장하고 이전 테이블을 삭제한 다음 FK 제약 조건을 사용하여 새 테이블을 만든 다음 임시 테이블에서 데이터를 다시 복사해야 합니다.(sqlite.org - FAQ: Q11)

표를 변경하고 제약 조건을 사용하는 열을 추가하는 경우 제약 조건을 추가할 수 있습니다.

먼저 parent_id가 없는 테이블을 만듭니다.

CREATE TABLE child( 
  id INTEGER PRIMARY KEY,  
  description TEXT);

그런 다음 테이블을 변경합니다.

ALTER TABLE child ADD COLUMN parent_id INTEGER REFERENCES parent(id);

https://www.sqlite.org/lang_altertable.html#otheralter 을 확인해주시기 바랍니다.

SQLite에서 직접 지원하는 스키마 변경 명령은 위에 표시된 "이름 변경 테이블"과 "열 추가" 명령뿐입니다.그러나 응용프로그램은 간단한 연산 순서를 사용하여 테이블 형식을 임의로 변경할 수 있습니다.일부 테이블 X의 스키마 설계를 임의로 변경하는 단계는 다음과 같습니다.

  1. 외부 키 제약 조건이 활성화된 경우, PRAGMA foreign_keys=를 사용하여 비활성화합니다.쉬는.
  2. 거래를 시작합니다.
  3. 테이블 X와 관련된 모든 인덱스 및 트리거의 형식을 기억합니다.이 정보는 아래 8단계에서 필요합니다.한 가지 방법은 SELECT type, sql FROM sqlite_master WHERE tbl_name='X'와 같은 쿼리를 실행하는 것입니다.
  4. CREATE TABLE을 사용하여 원하는 수정 형식의 테이블 "new_X"를 새로 구성합니다.물론 "new_X"라는 이름이 기존 테이블 이름과 충돌하지 않아야 합니다.
  5. INSERT INTO new_X SELECT ... FROM X와 같은 문을 사용하여 X에서 new_X로 내용을 전송합니다.
  6. 기존 테이블 X: Drop TABLE X를 드롭합니다.
  7. ALTER TABLE new_X RENE TO X를 사용하여 new_X의 이름을 X로 변경합니다.
  8. CREATE INDEX 및 CREATE TRIGER를 사용하여 테이블 X와 연관된 인덱스와 트리거를 재구성합니다.위의 3단계에서 저장된 트리거 및 인덱스의 이전 형식을 지침으로 사용하여 변경에 적합하도록 변경할 수 있습니다.
  9. 스키마 변경에 영향을 받는 방식으로 테이블 X를 참조하는 뷰가 있으면 DROP VIEW를 사용하여 해당 뷰를 삭제하고 CREATE VIEW를 사용하여 스키마 변경을 수용하는 데 필요한 모든 변경 사항으로 해당 뷰를 재생성합니다.
  10. 외부 키 제약 조건이 원래 활성화된 경우 PRAGMA foreign_key_check를 실행하여 스키마 변경이 외부 키 제약 조건을 위반하지 않았는지 확인합니다.
  11. 2단계에서 시작한 트랜잭션을 커밋합니다.
  12. 외부 키 제약 조건이 원래 활성화된 경우 지금 다시 활성화합니다.

위의 절차는 완전히 일반적이며 스키마 변경으로 인해 테이블에 저장된 정보가 변경되더라도 작동합니다.따라서 위의 전체 절차는 열을 삭제하거나, 열 순서를 변경하거나, UNIQUE 제약 조건 또는 Primary KEY를 추가 또는 제거하거나, CHECK 또는 FORINE KEY 또는 NOT NULL 제약 조건을 추가하거나, 열에 대한 데이터 유형을 변경하는 데 적합합니다.

예, 열을 새로 추가하지 않아도 가능합니다.데이터베이스가 손상되지 않도록 주의해야 하므로 이 작업을 시도하기 전에 데이터베이스를 완전히 백업해야 합니다.

구체적인 예를 들어:

CREATE TABLE child(
  id INTEGER PRIMARY KEY,
  parent_id INTEGER,
  description TEXT
);

--- create the table we want to reference
create table parent(id integer not null primary key);

--- now we add the foreign key
pragma writable_schema=1;
update SQLITE_MASTER set sql = replace(sql, 'description TEXT)',
    'description TEXT, foreign key (parent_id) references parent(id))'
) where name = 'child' and type = 'table';

--- test the foreign key
pragma foreign_keys=on;
insert into parent values(1);
insert into child values(1, 1, 'hi'); --- works
insert into child values(2, 2, 'bye'); --- fails, foreign key violation

또는 일반적으로 다음과 같은 경우:

pragma writable_schema=1;

// replace the entire table's SQL definition, where new_sql_definition contains the foreign key clause you want to add
UPDATE SQLITE_MASTER SET SQL = new_sql_definition where name = 'child' and type = 'table';

// alternatively, you might find it easier to use replace, if you can match the exact end of the sql definition
// for example, if the last column was my_last_column integer not null:
UPDATE SQLITE_MASTER SET SQL = replace(sql, 'my_last_column integer not null', 'my_last_column integer not null, foreign key (col1, col2) references other_table(col1, col2)') where name = 'child' and type = 'table';

pragma writable_schema=0;

어느 쪽이든 변경하기 전에 SQL 정의가 무엇인지 먼저 확인해야 할 것입니다.

select sql from SQLITE_MASTER where name = 'child' and type = 'table';

replace() 접근법을 사용하는 경우 실행하기 전에 다음을 실행하여 replace() 명령을 먼저 테스트하는 것이 도움이 될 수 있습니다.

select replace(sql, ...) from SQLITE_MASTER where name = 'child' and type = 'table';

다음을 시도해 볼 수 있습니다.

ALTER TABLE [Child] ADD COLUMN column_name INTEGER REFERENCES parent_table_name(column_id);

@다니엘 바살로가 말했듯이, 당신은 그것을 할 수 없습니다.사용해야 하는 코드는 다음과 같습니다.

주어진 표:

CREATE TABLE child( 
id INTEGER PRIMARY KEY, 
parent_id INTEGER, 
description TEXT);

다음 Foreignk Key를 추가할 것으로 가정합니다.

FOREIGN KEY (parent_id) REFERENCES parent(id);

그래서 이 테이블을 기반으로 임시 테이블을 작성한 다음 첫 번째 테이블로 새 테이블을 작성하고 마지막으로 임시 테이블의 데이터를 추가합니다.

CREATE TEMPORARY TABLE temp AS
SELECT 
    id,
    parent_id,
    description
FROM child;

DROP TABLE child;

CREATE TABLE child (
    id INTEGER PRIMARY KEY, 
    parent_id INTEGER, 
    description TEXT,
    FOREIGN KEY(parent_id) REFERENCES parent(id));

INSERT INTO child
 (  id,
    parent_id,
    description)
SELECT
    id,
    parent_id,
    description
FROM temp;

Firefox add-on sqlite-manager를 사용하는 경우 다음을 수행할 수 있습니다.

테이블을 삭제하고 다시 만드는 대신 이렇게 수정하면 됩니다.

Columns(열) 텍스트 상자에서 나열된 마지막 열 이름을 마우스 오른쪽 버튼으로 클릭하여 상황에 맞는 메뉴를 불러오고 Edit Column(열 편집)을 선택합니다.TABLE 정의의 마지막 열이 Primary KEY이면 먼저 새 열을 추가한 다음 새 열의 열 유형을 편집해야 FORNER KEY 정의를 추가할 수 있습니다.열 유형 상자에 쉼표를 추가하고

FOREIGN KEY (parent_id) REFERENCES parent(id)

데이터 형식 뒤의 정의.Change(변경) 버튼을 클릭한 다음 Dangerous Operation(위험 작업) 대화 상자에서 Yes(예) 버튼을 클릭합니다.

참조: Sqlite Manager

sqlite에 대해 Db Browser를 사용하면 테이블을 수정하기가 쉬워집니다.질의를 작성하지 않고 기존 테이블에 외래키를 추가할 수 있습니다.

  • DB 브라우저에서 데이터베이스를 엽니다.
  • 테이블을 마우스 오른쪽 버튼으로 클릭하고 수정을 클릭하면,
  • 거기서 외국 키 열로 스크롤하면,
  • 변경할 필드를 두 번 클릭합니다.
  • 그런 다음 테이블과 필드를 선택하고 확인을 클릭합니다.

바로 그겁니다.기존 테이블에 외국키를 추가하였습니다.

기존 SQLLite 테이블에 대한 외부 키 생성:

SQL LITE에는 직접적인 방법이 없습니다.아래 쿼리를 실행하여 외부 키로 학생 테이블을 다시 만듭니다.초기 Students 테이블을 생성하고 테이블에 데이터를 삽입한 후 쿼리를 실행합니다.

CREATE TABLE    STUDENTS    (       
    STUDENT_ID  INT NOT NULL,   
    FIRST_NAME  VARCHAR(50) NOT NULL,   
    LAST_NAME   VARCHAR(50) NOT NULL,   
    CITY    VARCHAR(50) DEFAULT NULL,   
    BADGE_NO    INT DEFAULT NULL
    PRIMARY KEY(STUDENT_ID) 
);

학생 테이블에 데이터를 삽입합니다.

그러면 외국인 키 추가 : BADGE_NO를 동일한 학생 테이블의 외국인 키로 만들기

BEGIN;
CREATE TABLE STUDENTS_new (
    STUDENT_ID  INT NOT NULL,   
    FIRST_NAME  VARCHAR(50) NOT NULL,   
    LAST_NAME   VARCHAR(50) NOT NULL,   
    CITY    VARCHAR(50) DEFAULT NULL,   
    BADGE_NO    INT DEFAULT NULL,
    PRIMARY KEY(STUDENT_ID) ,
    FOREIGN KEY(BADGE_NO) REFERENCES STUDENTS(STUDENT_ID)   
);
INSERT INTO STUDENTS_new SELECT * FROM STUDENTS;
DROP TABLE STUDENTS;
ALTER TABLE STUDENTS_new RENAME TO STUDENTS;
COMMIT;

우리는 다른 테이블에서도 외국키를 추가할 수 있습니다.

다른 사람이 SQLiteStudio에 대한 정보가 필요한 경우에는 GUI를 통해 쉽게 사용할 수 있습니다.

열을 두 번 클릭하고 외부 키 행을 두 번 클릭한 다음 외부 키를 선택하고 구성을 클릭합니다.참조 열을 추가한 다음 모든 창에서 확인을 클릭할 수 있습니다.

마지막으로 녹색 체크 표시를 클릭하여 구조의 변경 사항을 커밋합니다.

다음 단계에서는 테이블을 삭제하고 다시 만드는 SQL 스크립트를 생성합니다.!!

데이터베이스에서 데이터를 백업합니다.

@Gaurav Ganani 설명을 시각적으로 완성하기 위해, 저는 잘 작동했습니다(그리고 DB Browser for SQLite를 사용하는 사람들에게도 잘 작동하기를 바랍니다). 여기에 이 이미지를 붙여넣겠습니다.

enter image description here

데이터베이스를 열고 테이블을 마우스 오른쪽 단추로 클릭한 다음 데이터베이스 수정을 선택합니다.열려 있는 창에서 외부 키를 만들고자 하는 열을 선택하고 오른쪽으로 스크롤하면 열로 쓰여진 외부 키를 찾을 수 있고 참조하고 있는 테이블에 열을 더해서 쉽게 선택할 수 있습니다.

기본적으로 당신은 할 수 없지만 그 상황을 우회할 수 있습니다.

기존 테이블에 외부 키 제약 조건을 추가하는 올바른 방법은 다음 명령입니다.

db.execSQL("alter table child add column newCol integer REFERENCES parent(parent_Id)");

그런 다음 Parent_Id 데이터를 newCol에 복사한 다음 Parent_Id 열을 삭제합니다.따라서 임시 테이블이 필요 없습니다.

먼저 하위 테이블에 열 추가Cid~하듯이int그리고나서alter table아래의 코드로이 방법으로 외국 키를 추가할 수 있습니다.Cid부모 테이블의 기본 키로 사용하고 자식 테이블의 외부 키로 사용합니다...나에게 좋은 일이기 때문에 당신에게 도움이 되기를 바랍니다.

ALTER TABLE [child] 
  ADD CONSTRAINT [CId] 
  FOREIGN KEY ([CId]) 
  REFERENCES [Parent]([CId]) 
  ON DELETE CASCADE ON UPDATE NO ACTION;
GO

언급URL : https://stackoverflow.com/questions/1884818/how-do-i-add-a-foreign-key-to-an-existing-sqlite-table

반응형