Python: Как отсортировать инструкции SQL в текстовом файле?

#python #sql

#python #sql

Вопрос:

Приведенный ниже вывод взят из Oracle; где он генерирует инструкции «create table» с использованием прилагаемого пакета. Я загружаю их в инструмент python diff HtmlDiff, который использует difflib под обложками. За каждой таблицей следует ряд команд «alter table add constraint», которые добавляют различные ограничения.

Проблема в том, что нет явного порядка команд «alter table», и я должен изменить их порядок после создания выходного файла, прежде чем запускать сравнение. Мне нужна помощь в этом; в идеале с использованием python, sed или awk.

Правила будут после каждой строки, содержащей «СОЗДАТЬ ТАБЛИЦУ», до следующей строки, содержащей «СОЗДАТЬ ТАБЛИЦУ», сортировать каждую строку, содержащую «ДОБАВИТЬ ОГРАНИЧЕНИЕ»

Это пример моего вывода:

     CREATE TABLE T1
    (     BOOK_ID NUMBER NOT NULL ENABLE,
      LOCATION_ID NUMBER NOT NULL ENABLE,
             NAME VARCHAR2(255) NOT NULL ENABLE,
     LEGAL_ENTITY VARCHAR2(255) NOT NULL ENABLE,
           STATUS CHAR(1) NOT NULL ENABLE
    ) ;

ALTER TABLE T1 ADD CONSTRAINT T1_CHK_1 CHECK ( status IN ( 'A', 'I' , 'T' ) ) ENABLE;
ALTER TABLE T1 ADD CONSTRAINT T1_PK PRIMARY KEY (BOOK_ID) ENABLE;
ALTER TABLE T1 ADD CONSTRAINT T1_AK_1 UNIQUE (NAME) ENABLE;
ALTER TABLE T1 ADD CONSTRAINT T1_FK_1 FOREIGN KEY (LOCATION_ID) REFERENCES T6 (LOCATION_ID) ENABLE;

CREATE TABLE T2
        (    
                    BUCKET_ID NUMBER  NOT NULL ENABLE,
         DATA_LOAD_SESSION_ID NUMBER,
                    IS_LOCKED CHAR(1) NOT NULL ENABLE,
               LOCK_DATE_TIME DATE
        ) ;
ALTER TABLE T2 ADD CONSTRAINT CKC_IS_LOCKED_BUCKET CHECK (IS_LOCKED in ('T','F')) ENABLE;
ALTER TABLE T2 ADD CONSTRAINT T2_PK PRIMARY KEY (BUCKET_ID) ENABLE;
ALTER TABLE T2 ADD CONSTRAINT T2_FK_2 FOREIGN KEY (RRDB_STAGING_TABLE_ID) REFERENCES T4 (RRDB_STAGING_TABLE_ID) ENABLE;

CREATE TABLE T3
        (                   VALUE_DATE DATE,
                               NODE_ID NUMBER,
                            RESULT_UID VARCHAR2(255),
         LATEST_EOD_SING_VAL_RESULT_ID NUMBER NOT NULL ENABLE
        )
ALTER TABLE T3 ADD CONSTRAINT T3_PK PRIMARY KEY (VALUE_DATE, NODE_ID, RESULT_UID) ENABLE;
  

Желаемый результат: единственное отличие заключается в порядке строк «ДОБАВИТЬ ОГРАНИЧЕНИЕ»

 CREATE TABLE T1
    (     BOOK_ID NUMBER NOT NULL ENABLE,
      LOCATION_ID NUMBER NOT NULL ENABLE,
             NAME VARCHAR2(255) NOT NULL ENABLE,
     LEGAL_ENTITY VARCHAR2(255) NOT NULL ENABLE,
           STATUS CHAR(1) NOT NULL ENABLE
    ) ;
ALTER TABLE T1 ADD CONSTRAINT T1_AK_1 UNIQUE (NAME) ENABLE;
ALTER TABLE T1 ADD CONSTRAINT T1_CHK_1 CHECK ( status IN ( 'A', 'I' , 'T' ) ) ENABLE;
ALTER TABLE T1 ADD CONSTRAINT T1_FK_1 FOREIGN KEY (LOCATION_ID) REFERENCES T6 (LOCATION_ID) ENABLE;
ALTER TABLE T1 ADD CONSTRAINT T1_PK PRIMARY KEY (BOOK_ID) ENABLE;

CREATE TABLE T2
    (    
                BUCKET_ID NUMBER  NOT NULL ENABLE,
     DATA_LOAD_SESSION_ID NUMBER,
                IS_LOCKED CHAR(1) NOT NULL ENABLE,
           LOCK_DATE_TIME DATE
    ) ;
ALTER TABLE T2 ADD CONSTRAINT CKC_IS_LOCKED_BUCKET CHECK (IS_LOCKED in ('T','F')) ENABLE;
ALTER TABLE T2 ADD CONSTRAINT T2_FK_2 FOREIGN KEY (RRDB_STAGING_TABLE_ID) REFERENCES T4 (RRDB_STAGING_TABLE_ID) ENABLE;
ALTER TABLE T2 ADD CONSTRAINT T2_PK PRIMARY KEY (BUCKET_ID) ENABLE;

CREATE TABLE T3
    (                   VALUE_DATE DATE,
                           NODE_ID NUMBER,
                        RESULT_UID VARCHAR2(255),
     LATEST_EOD_SING_VAL_RESULT_ID NUMBER NOT NULL ENABLE
    )
ALTER TABLE T3 ADD CONSTRAINT T3_PK PRIMARY KEY (VALUE_DATE, NODE_ID, RESULT_UID) ENABLE;
  

Ответ №1:

Загрузите все это в строку, затем разделите на «;», чтобы создать массив команд SQL. Зациклите массив и создайте новый отсортированный массив. Передайте биты CREATE TABLE и выделите инструкции ALTER TABLE в отдельный список. отсортируйте() список изменений и расширьте его до результирующего массива. Когда вы закончите, ';n'.join(result_array) ';' .

Ответ №2:

Быстро и грязно, но я думаю, что это подойдет для вашего случая (наверняка сработало в примере):

 conList = []
for ln in f:
    if ' ADD CONSTRAINT ' in ln:
        conList.append(ln)
    else:
        for it in sorted(conList):
            print it
        conList = []
        print ln
# finish any unfinished business 
for it in sorted(conList):
    print it