1 Востаннє редагувалося Lujok (01.10.2015 11:45:22)

Тема: Видалення колонки з таблиці БД SQLite ( декілька запитань ) .

Я знаю, щоб видалити колонку в БД SQLite треба :
- створити нову таблицю (без колонки яку треба видалити),
- перенести дані зі старої таблиці в нову,
- видалити стару таблицю,
- та переіменувати нову таблицю.
Я для початку створюю копію таблиці , зі всіма колонками (потім збираюсь робити без колонки яку треба видалити). Виникли питання :
1 . Як в цілому мій код (нижче) ?
спочатку я Створюю нову таблицю з однією колонкою ІД.
потім         Добавляю в нову таблицю колонки
              - Вставляю  в нову таблицю  строки ( INSERT INTO...). Лишу  поле ІД буде заповнене даними
              - За допомогою    update   добавляю дані в інші поля (крім ІД) 
2.  довелось двічі писати  rs = statmt.executeQuery("SELECT * FROM " + tableName); інакше в циклі while  не вставлялися дані в нову таблицю.  Чому ?
3.  Питання стосується двійних та одинарних лапок . Коли треба двійні, а коли двійні та одинарні  ?
String sql1Update = " update  '"+newTableName+"' set "+colNamesList.get(i)+" = '"+ obj[n]+"'  where id = "+ obj[0]+" ";                             //   '"+ obj[n]+"' -  пишу в двійних та одинарних лапках. Інакше добавити текстові дані не вдавалося, тільки числа .
4. Ще я не раз використовую Statement statmt та PreparedStatement prstm для виконання різних запитів. Коли  їх  треба закривати -  щоразу після використання чи достатньо одного разу в кінці метода ?




Ось код:
де:
tableName - ім'я старої таблиці
colNamesList - список (колекція імен колонок )
colTypesList - список  типів колонок

public void RemoweColumn ()  {
        try {
            PreparedStatement prstm =null;
            Statement statmt = null;
            statmt= conn.createStatement();

    rs = statmt.executeQuery("SELECT * FROM " + tableName);    //  1-й раз роблю запит

     colTypesList.clear();

     for(int n=1;n <=colNamesList.size();n++){
            colTypesList.add(rs.getMetaData().getColumnTypeName(n));
          }

// Створюю нову таблицю з однією колонкою ІД (colNamesList.get(0))
         String newTableName = tableName +"Copy";
              String sql =  "CREATE TABLE ["+newTableName+"] (["+colNamesList.get(0) +"] INTEGER)";
              statmt.execute(sql);


//Добавляю в нову таблицю колонки    
          
              for(int n=1;n<colNamesList.size(); n++){  
                 String  AddColumn = "Alter Table "+newTableName+"  ADD  '"+colNamesList.get(n) +"'  '"+ colTypesList.get (n)+"' " ;
                 statmt.execute(AddColumn);
            }
             rs = statmt.executeQuery("SELECT * FROM " + tableName);  //  2-й раз доводиться  робити запит
           
// В  циклі заповнюю даними нову таблицю
           while(rs.next()){

           Object[] obj = new Object[colNamesList.size()] ; // В [b] obj [/b] зберігається одна строка 

           for(int n=0; n<colNamesList.size(); n++){ 
                   obj[n] =  rs.getObject(colNamesList.get(n));      
                }

// Вставляю  в нову таблицю  строки ( INSERT INTO...). Лише  поле ІД буде заповнене даними

             String sqlInsert = " INSERT INTO   '"+newTableName+"' ("+colNamesList.get(0)+")  VALUES("+ obj[0]+")";
                 prstm = conn.prepareStatement(sqlInsert);
                 prstm.executeUpdate();
                 if (prstm!=null )prstm.close(); 

       // За допомогою    update   добавляю дані в інші поля (крім ІД)      
          for( int n = 1; n< colNamesList.size(); n++){
                    String sql1Update = " update  '"+newTableName+"' set "+colNamesList.get(n)+" = '"+ obj[n]+"'  where id = "+ obj[0]+" ";                                  //   '"+ obj[n]+"'  -  пишу в двійних та одинарних лапках. Інакше добавити текстові дані не вдавалося, тільки числа .

                prstm = conn.prepareStatement(sql1Update);
                     prstm.executeUpdate();
                     if (prstm!=null )prstm.close();
                }
            }
            if (statmt!=null )statmt.close();
            if (prstm!=null ) try {
             prstm.close();
             } catch (SQLException ex) {
                 Logger.getLogger(TM.class.getName()).log(Level.SEVERE, null, ex);
             }
        } catch (SQLException ex) {
            Logger.getLogger(TM.class.getName()).log(Level.SEVERE, null, ex);
        }
     }

2

Re: Видалення колонки з таблиці БД SQLite ( декілька запитань ) .

З SQLite тільки почав пару днів назад знайомство, тому можу помилятися, але здаэться, що там можна створювати таблицю з SELECTa,  чому б не скористатися:

create table newTable as select * from oldTable;

Замість зірочки вказуэте, які рядки залишаються в новій таблиці.

3 Востаннє редагувалося P.Y. (01.10.2015 00:07:44)

Re: Видалення колонки з таблиці БД SQLite ( декілька запитань ) .

alter table в sqlite цього не вміє ? :(

py -3 -m pip install git+https://github.com/snoack/python-goto
∩⍴○⌈⍴⍺/∧\∨/⊢○ ⌿⍀⍴⌊

4

Re: Видалення колонки з таблиці БД SQLite ( декілька запитань ) .

SQLite alter table не може видалити колонку (поле) з таблиці + не може змінювати колонку (поле).
SQLite alter table може перейменувати таблицю + додати колонку (поле).

5

Re: Видалення колонки з таблиці БД SQLite ( декілька запитань ) .

На рахунок, коду, його важкувато читати, використовуйте тег code.
P.S. А чому, Ви не хочете користатися try з ресурсами?

6 Востаннє редагувалося Lujok (01.10.2015 11:53:31)

Re: Видалення колонки з таблиці БД SQLite ( декілька запитань ) .

fed_lviv написав:

З SQLite тільки почав пару днів назад знайомство, тому можу помилятися, але здаэться, що там можна створювати таблицю з SELECTa,  чому б не скористатися:

create table newTable as select * from oldTable;

Замість зірочки вказуэте, які рядки залишаються в новій таблиці.

colNamesList   - список імен колонок .
tableName  - стара таблиця.

String sql =  "CREATE TABLE  "+newTableName+" AS SELECT  '"+colNamesList.get(0) +"' ,  '"+colNamesList.get(1) +"'  FROM '"+tableName+"' " ; 

результат такого запиту нова таблиця з конкретнною колонкою , але замість даних в усіх рядках назва колонки.

Post's attachments

замість_даних_імена_колонок.png 784 b, 86 downloads since 2015-10-01 

7 Востаннє редагувалося fed_lviv (01.10.2015 13:30:00)

Re: Видалення колонки з таблиці БД SQLite ( декілька запитань ) .

Ось наприклад:

.echo on
.headers on
.mode column
.nullvalue NULL

CREATE TABLE IF NOT EXISTS gas (
        idGas INTEGER PRIMARY KEY,
        amount INTEGER NOT NULL,
        transmit INTEGER NOT NULL DEFAULT 0,
        finally INTEGER NOT NULL DEFAULT 0,
        change TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO gas (amount) VALUES (100);
SELECT * FROM gas;
CREATE TABLE tab AS SELECT idGas, amount FROM gas;
SELECT * FROM tab;

Результат:

Post's attachments

1.jpg 107.94 kb, 107 downloads since 2015-10-01 

8 Востаннє редагувалося Lujok (02.10.2015 11:14:23)

Re: Видалення колонки з таблиці БД SQLite ( декілька запитань ) .

Lujok написав:
colNamesList   - список імен колонок .
tableName  - стара таблиця.

String sql =  "CREATE TABLE  "+newTableName+" AS SELECT  '"+colNamesList.get(0) +"' ,  '"+colNamesList.get(1) +"'  FROM '"+tableName+"' " ; 

результат такого запиту нова таблиця з конкретнною колонкою , але замість даних в усіх рядках назва колонки.

Прибрав одинарні лапки   "+colNamesList.get(n) +"   і зявилися данні.  АЛЕ для цикла цей запит не підходить .   Вставляє лише першу колонку з даними. А мені треба щоб усі і наперед невідомо скільки колонок там буде.

for(int n=0; n < colNamesList.size(); n++){
                  String sql =  "CREATE TABLE  IF NOT EXISTS  "+newTableName+" AS SELECT  "+colNamesList.get(n) +"  FROM "+tableName+"  " ; 
                  statmt= conn.createStatement();
                  statmt.executeUpdate(sql);
            }

Одже ,мабудь ,  за допомогою цього запиту створюватиму нову таблицю з одним полем , потім добавляти інші поля ( Alter Table "+newTableName+"  ADD ...),   а потім вже за допомогою UPDATE  добавляти дані в ці поля.

9 Востаннє редагувалося fed_lviv (02.10.2015 11:44:03)

Re: Видалення колонки з таблиці БД SQLite ( декілька запитань ) .

Ви мене остаточно заплутали. Я  вже не розумію, що Вам потрібно.

...наперед невідомо скільки колонок там буде

Чому невідомо??? Ви ж хочете з старої таблиці просто видалити колонку(колонки), тобто в новій таблиці буде все те саме окрім, тих колонок, які видалені.
Не хочете

create table newTable as select * from oldTable;

Скористайтеся:

create table newTable (...;
insert into newTable select * from oldTable;

*-замініть на потрібні поля.

10 Востаннє редагувалося Lujok (02.10.2015 12:08:56)

Re: Видалення колонки з таблиці БД SQLite ( декілька запитань ) .

fed_lviv написав:
Ви мене остаточно заплутали. Я  вже не розумію, що Вам потрібно.
...наперед невідомо скільки колонок там буде
Чому невідомо??? Ви ж хочете з старої таблиці просто видалити колонку(колонки), тобто в новій таблиці буде все те саме окрім, тих колонок, які видалені.

в циклі добавляє лише одну колонку  .

create table newTable as select "+colNamesList.get(n) +"  from oldTable; 


Або ті які прямо прописані в SQL запиті

create table newTable as select pole1, pole2... from oldTable; 

Я не можу прямо прописати імена колонок , бо я не можу знати які там будуть

11

Re: Видалення колонки з таблиці БД SQLite ( декілька запитань ) .

Lujok написав:

Я не можу прямо прописати імена колонок , бо я не можу знати які там будуть

Добре, давайте так:
1. Є таблиця tab1 з полями (col1, col2, col3)
2. Є список з назвами колонок list
3. Користувач хоче видалити поле col2. З списку list видаляєм col2.
4. Створюємо запит. В циклі пробігаємося по списку list.
5. Запускаєм запит.
Що з переліку Вам не подобається?

12 Востаннє редагувалося Lujok (02.10.2015 12:57:56)

Re: Видалення колонки з таблиці БД SQLite ( декілька запитань ) .

fed_lviv написав:
Lujok написав:

Я не можу прямо прописати імена колонок , бо я не можу знати які там будуть

Добре, давайте так:
1. Є таблиця tab1 з полями (col1, col2, col3)
2. Є список з назвами колонок list
3. Користувач хоче видалити поле col2. З списку list видаляєм col2.
4. Створюємо запит. В циклі пробігаємося по списку list.
5. Запускаєм запит.
Що з переліку Вам не подобається?

В циклі добавляється лише одна колонка. якщо прибрати з запиту  IF NOT EXISTS , то  каже що така таблиця вже існує.  Тобто з кожною ітерацією цикла створюється  нову таблицю... А як тоді в циклі  за допомогою 

"CREATE TABLE  IF NOT EXISTS  "+newTableName+" AS SELECT..

. добавляти не одну колонку  ?
   

  for(int n =0; n < colNamesList.size(); n++){
                  String sql =  "CREATE TABLE  IF NOT EXISTS  "+newTableName+" AS SELECT  "+colNamesList.get(n) +"  FROM "+tableName+"  " ; 
                  statmt= conn.createStatement();
                  statmt.executeUpdate(sql);
            }

13

Re: Видалення колонки з таблиці БД SQLite ( декілька запитань ) .

Я ж Вам спеціально виділив Створюємо запит. Тобто беремо StringBuffer або StringBuilder, ну якщо є бажання можете взяти String. І створюєте об'єкт класа StringBuffer/StringBuilder/String query;
В циклі не потрібно відправляти запит, в циклі створюєте тільки запит - String. А пункт 5 виконаєте після створення запиту.

Подякували: Lujok1

14 Востаннє редагувалося fed_lviv (02.10.2015 14:33:07)

Re: Видалення колонки з таблиці БД SQLite ( декілька запитань ) .

StringBuffer query = new StringBuffer("CREATE TABLE newTable AS SELECT ");
for(int i=0; i<list.size(); i++){
   query.append(list.get(i)+", ");
}
query.deleteCharAt(query.length()-1);
query.append("FROM oldTable;");
query.toString();
Подякували: Lujok1

15 Востаннє редагувалося Lujok (02.10.2015 20:41:12)

Re: Видалення колонки з таблиці БД SQLite ( декілька запитань ) .

fed_lviv написав:

Я ж Вам спеціально виділив Створюємо запит. Тобто беремо StringBuffer або StringBuilder, ну якщо є бажання можете взяти String. І створюєте об'єкт класа StringBuffer/StringBuilder/String query;
В циклі не потрібно відправляти запит, в циклі створюєте тільки запит - String. А пункт 5 виконаєте після створення запиту.

Я такого ще не вчив , дякую буду вивчати .
В мене ось як вийшло :
     

String sqlSTR = " " ;
               for(int n=0; n < colNamesList.size(); n++){
                    String colN = colNamesList.get(n);
                   if(n==0){
                       sqlSTR += colN ;
                   }else{
                      sqlSTR += " , "+colN ;
                   }
               }
          
             String sqlSTRSQL =  "CREATE TABLE  IF NOT EXISTS  "+newTableName+" AS SELECT  "+sqlSTR +"  FROM "+tableName+"  " ; 
        statmt= conn.createStatement();
          statmt.executeUpdate(sqlSTRSQL);

16

Re: Видалення колонки з таблиці БД SQLite ( декілька запитань ) .

Тільки, я б Вам рекомендував, замість Stringа, вибрати, щось з цього: StringBuffer або StringBuilder

Подякували: quez1

17

Re: Видалення колонки з таблиці БД SQLite ( декілька запитань ) .

fed_lviv написав:

Тільки, я б Вам рекомендував, замість Stringа, вибрати, щось з цього: StringBuffer або StringBuilder

Добре ,  ще раз дякую що допомагаєте мені !

18

Re: Видалення колонки з таблиці БД SQLite ( декілька запитань ) .

:[ Та будь-ласка.

19

Re: Видалення колонки з таблиці БД SQLite ( декілька запитань ) .

Ще питання.  Коли створюється нова таблиця за допомогою "

CREATE TABLE    ...AS SELECT ...FROM ..."

  то в новій таблиці поле ID не встановлене в

primary key 

,

avtoincrement  

на відміну від старої .
Я зрозумів що можно за допомогою  rs.getMetaData().isAutoIncrement(1)  узнавати яке поле в старій таблиці установлене в isAutoIncrement:

if(rs.getMetaData().isAutoIncrement(1)){
                System.out.println("rs.getMetaData().isAutoIncrement(1)-- true ");
            }else{
                 System.out.println("rs.getMetaData().isAutoIncrement(1) -- false");
            }

Тепер завдання , як таке ж поле в новій таблиці установити isAutoIncrement ?

20 Востаннє редагувалося fed_lviv (05.10.2015 22:11:26)

Re: Видалення колонки з таблиці БД SQLite ( декілька запитань ) .

Так дійсно при:

CREATE TABLE newTable FROM SELECT * FROM oldTable

таблиця не маэ жодних обмежень, унікальних значень, автоінкрементів і тд. Тому прийдеться йти другим варіантом, який я Вам пропонував, два запити:

create table newTable (...;
insert into newTable select * from oldTable;