Skysnake

SQLite Alter Table Drop Column (with some AutoIt magic)

1 post in this topic

#1 ·  Posted (edited)

#cs ----------------------------------------------------------------------------

    AutoIt Version: 3.3.14.0
    Author:         Skysnake
    Date:           2016.05.17

    Script Function:
    Alter table drop column.

    By way of example the original table has these three columns:
    name,surname,nickname
    to be replaced with
    name,surname,number

    "We cannot drop a specific column in SQLite 3. See the FAQ. It is not possible to
    rename a column, remove a column, or add or remove constraints from a table.
    While you can always create a new table and then drop the older one.Dec 9, 2011"

    http://stackoverflow.com/questions/8442147/how-to-delete-or-add-column-in-sqlite


    The only ALTER TABLE functions that SQLite supports are those that can be
    accomplished without having to rewrite the entire table.  Or, to put it
    another way, the only ALTER TABLE functions supported are those that can be
    done in O(1) time.

    ALTER TABLE DROP COLUMN requires writing every row of the table.

    D. Richard Hipp

    http://sqlite.1065341.n5.nabble.com/Why-can-t-SQLite-drop-columns-td64687.html

    Notes:
    Required original array size of table to be altered (zero count +1)
    Required the name of the column to drop
    Required full "create table ..." syntax for new column eg: , number  text   not null default 'Contact Number')


#ce ----------------------------------------------------------------------------

; Script Start - Add your code below here
; SQLite.dll version must match

#include <Array.au3>
#include <MsgBoxConstants.au3>
#include <SQLite.au3>
#include <SQLite.dll.au3>

Local Const $iMax = 6 ; this is the current table column count
Local $query, $aResult, $iRows, $iColumns, $ColName, $sMsg, $mySQLdb, $aLessColmns[$iMax][1] ; will require only one column
Local $sNewColNames


Local $sLocalSQLiteDll = "sqlite3_win32-x86-3120100.dll" ;

Local $sSQliteDll = _SQLite_Startup($sLocalSQLiteDll, False, 1)
If @error Then
    MsgBox($MB_SYSTEMMODAL, "SQLite Error", "SQLite3.dll Can't be Loaded!" & @CRLF & @CRLF & _
            "Not FOUND in @SystemDir, @WindowsDir, @ScriptDir, @WorkingDir or from www.autoitscript.com")
    Exit -1
EndIf

ConsoleWrite("_SQLite_LibVersion=" & _SQLite_LibVersion() & @CRLF)
$mySQLdb = _SQLite_Open(@ScriptDir & '\mydb.sql3')


; Without $sCallback it's a resultless statement
; ..................................................... create table tORiginal for System Info
$query = "CREATE TABLE if not exists tORiginal ( " _
         & "id  integer primary     key         unique not null " _
         & ", name                  text        not null default 'First Name' " _
         & ", surname               text        not null default 'Surname' " _
         & ", nickname              text        not null default 'Nickname' " _
         & ", RegDate               text        NOT NULL DEFAULT current_timestamp " _
         & " ) ; "

If Not _SQLite_Exec($mySQLdb, $query) = $SQLITE_OK Then _
        MsgBox($MB_SYSTEMMODAL, "SQLite Error", _SQLite_ErrMsg() & " * " & @ScriptLineNumber)

ConsoleWrite("SQL created tORiginal " & @CRLF)



; Without $sCallback it's a resultless statement
; ..................................................... create table tORiginal for System Info
$query = "Insert into tORiginal (name,surname,nickname) values ('John','Jones','Johnny') " _
         & "  ; "

If Not _SQLite_Exec($mySQLdb, $query) = $SQLITE_OK Then _
        MsgBox($MB_SYSTEMMODAL, "SQLite Error", _SQLite_ErrMsg() & " * " & @ScriptLineNumber)

ConsoleWrite("SQL data inserted into tORiginal " & @CRLF)



$query = " SELECT * FROM tORiginal " _
         & " ; "
; Query
; Query
$iRval = _SQLite_GetTable2d($mySQLdb, $query, $aResult, $iRows, $iColumns)
If $iRval = $SQLITE_OK Then
    ConsoleWrite("$SQLITE_OK at Line " & $SQLITE_OK & " " &@ScriptLineNumber & @CRLF)
Else
    MsgBox($MB_SYSTEMMODAL, "SQLite Error: " & $iRval, _SQLite_ErrMsg())
EndIf

_ArrayDisplay($aResult, "CREATEd and INSERTed"  ) ; show the results of insert into SQL table

; https://www.sqlite.org/pragma.html#pragma_table_info
$query = " pragma table_info(tORiginal) " _
         & " ; "
; Query
; Query
$iRval = _SQLite_GetTable2d($mySQLdb, $query, $aResult, $iRows, $iColumns)
If $iRval = $SQLITE_OK Then
    ConsoleWrite("$SQLITE_OK at Line " & $SQLITE_OK & " " &@ScriptLineNumber & @CRLF)
Else
    MsgBox($MB_SYSTEMMODAL, "SQLite Error: " & $iRval, _SQLite_ErrMsg())
EndIf

_ArrayDisplay($aResult, "Pragma Result: Original Table") ; show the results of pragma

ConsoleWrite("SQL PRAGMA to find all columns " & @CRLF)

; this is the AutoIt magic
; SQLite does not allow manipulation of the pragma result, but
; AutoIt can process this result as normal query result
; delete column %id% from result
#cs
    Row|Col 0   |Col 1      |Col 2  |Col 3  |Col 4      |Col 5
    [0]|cid     |name       |type   |notnull|dflt_value |pk
    [1]|0       |id         |INTEGER|0      |           |1
    [2]|1       |Name       |       |0      |           |0
    [3]|2       |Surname    |       |0      |           |0
    [4]|3       |Nickname   |       |0      |           |0 ; >>>>>>>>> column to remove

#CE

;https://www.autoitscript.com/wiki/Arrays#Comparing_Arrays
Local $transfound = UBound($aResult, 1) - 1
For $i = 1 To $transfound Step +1
    ConsoleWrite($aResult[$i][1] & @CRLF)

    ; Check that the array is big enough
    If UBound($aLessColmns) = $i Then
        ; Resize the array when $i is equal to the element count in the array to prevent subscript error
        ReDim $aLessColmns[$aLessColmns[0] + $iMax]

    EndIf

    If StringRegExp($aResult[$i][1], "nick") Then ;>>>>>>>>> remove the column you dont want
        ; it may be dangerous to use a Regex here :)
        ; do nothing, do not add this column name
    Else
        $aLessColmns[$i][0] = $aResult[$i][1] ; safely add data to new index element

        $aLessColmns[0][0] = $i ; update the index count for future reference
    EndIf
Next

; for good measure
; Move backwards through the array deleting the blank lines
For $i = UBound($aLessColmns) - 1 To 0 Step -1
    If $aLessColmns[$i][0] = "" Then
        _ArrayDelete($aLessColmns, $i)
    EndIf
Next
$aLessColmns[0][0] = UBound($aLessColmns) - 1 ; update the index count for future reference

_ArrayDisplay($aLessColmns, "Column names from tORiginal less one") ; show the new array

$sNewColNames = _ArrayToString($aLessColmns, "|", 1, -1, ",") ; entire array
MsgBox(0, "$sNewColNames", $sNewColNames)
ConsoleWrite("New Column names " & $sNewColNames & @CRLF)
; now create a transient table, insert values, and rename

_SQLite_Exec($mySQLdb, "Create table tNewColumns (" & $sNewColNames & ", number             text        not null default 'Contact Number') ; " & _
        "Insert into tNewColumns (" & $sNewColNames & ") select " & $sNewColNames & " from  tORiginal " & _
        " ; ")


$query = " SELECT * FROM tNewColumns " _
         & " ; "
; Query
; Query
$iRval = _SQLite_GetTable2d($mySQLdb, $query, $aResult, $iRows, $iColumns)
If $iRval = $SQLITE_OK Then
    ConsoleWrite("$SQLITE_OK at Line " & $SQLITE_OK & @ScriptLineNumber & @CRLF)
Else
    MsgBox($MB_SYSTEMMODAL, "SQLite Error: " & $iRval, _SQLite_ErrMsg())
EndIf

_ArrayDisplay($aResult, "Results of new table") ; show the results of insert into SQL table

; https://www.sqlite.org/pragma.html#pragma_table_info
$query = " pragma table_info(tORiginal) " _
         & " ; "
; Query
; Query
$iRval = _SQLite_GetTable2d($mySQLdb, $query, $aResult, $iRows, $iColumns)
If $iRval = $SQLITE_OK Then
    ConsoleWrite("$SQLITE_OK at Line " & $SQLITE_OK & " " &@ScriptLineNumber & @CRLF)
Else
    MsgBox($MB_SYSTEMMODAL, "SQLite Error: " & $iRval, _SQLite_ErrMsg())
EndIf

_ArrayDisplay($aResult, "Pragma Result: altered Original Table") ; show the results of pragma

ConsoleWrite("SQL PRAGMA to find all columns " & @CRLF)


; now drop tORiginal
; https://www.sqlite.org/lang_altertable.html
; ALTER TABLE tNewColumns RENAME TO tORiginal


ConsoleWrite("_SQLite_Shutdown " & @CRLF)
_SQLite_Shutdown()
FileDelete($mySQLdb)

I believe it is suitable to post on this Forum, as it serves no purpose anywhere else.  I have searched, and except for some ancient threads referring to this, could find nothing similar.  

I used SQLite 3.12.1 which can be downloaded here Precompiled Binaries for Windows. I see they are up to 3.12.2 now.

Painfully obvious is of course that one must know the name of the offending column. :)

 

Edited by Skysnake
2016.06.04 Improved

Skysnake

Why is the snake in the sky?

Share this post


Link to post
Share on other sites



Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now

  • Similar Content

    • rynow
      By rynow
      romaSQL
      This autoIt UDF is built on the concept of Laravel Query & doctrine.
      RomaSQL provides a new, comfortable and easy to use way for SQL-queries in autoIt.
      Most of the common SQL-queries are supported already and more are coming soon.
      All of your support is much appreciated.
      Connections
      For the connection the object ADODB is used. Therefore the connection string is based on ODBC.
      You can also use OLEDB connection strings or other database connections.
      In order for this to work your add-ons have to be installed in the function: __4ern_SQL_Connection.
      I’d be very glad if you shared your modifications with me.
      Currently supported connections
      -       MySQL (odbc)
      -       Microsoft SQL Server (odbc)
      -       SQLite (odbc)
      -       Microsoft Access (odbc)
      Command reference
      $SQL_connect; establishing connection $SQL_returnType; return a Array or Dictionary ('oDict') Object (Default = Array) $SQL_setDefaultTable; Default Tablename $SQL_setDefaultKey; Default Colmn Key (Default = id) $SQL_debug; if True, show SQL Statment in Console $SQL_get $SQL_update $SQL_delete $SQL_insertInto $SQL_take $SQL_limit $SQL_table $SQL_select $SQL_distinct $SQL_where $SQL_orWhere $SQL_whereBetween $SQL_whereNotBetween $SQL_whereIn $SQL_whereNotIn $SQL_whereNull $SQL_whereNotNull $SQL_having $SQL_orHaving $SQL_havingBetween $SQL_havingNotBetween $SQL_havingIn $SQL_havingNotIn $SQL_havingNull $SQL_havingNotNull $SQL_groupBy $SQL_orderBy  
      Examples
      establishing connection
      ;-----/ ; SQLite Connection ;-----/ $SQL_setDatabase('sqlite') $SQL_connect('C:\project.db') ;-----/ ; Access Connection ; Database, User, Password ;-----/ $SQL_setDatabase('access') $SQL_connect('C:\project.mdb') ;or as Admin $SQL_connect('C:\project.mdb', '4ern', 'root') ;-----/ ; SQLServer Connection ; Database, User, Password, Server, Driver ;-----/ $SQL_setDatabase('sqlserver') $SQL_connect('myDB', '4ern', 'root', 'localhost') ;or with Driver $SQL_connect('myDB', '4ern', 'root', 'localhost', 'SQL Server') ;-----/ ; MySQL Connection ; Database, User, Password, Server, Driver ;-----/ $SQL_setDatabase('mysql') $SQL_connect('myDB', '4ern', 'root', 'localhost') ;or with Driver $SQL_connect('myDB', '4ern', 'root', 'localhost', 'MySQL ODBC 5.2 UNICODE Driver')  
      simple SQL query
      $SQL_table('albums') $aRet = $SQL_get() if IsArray($aRet ) then _ArrayDisplay($aRet ) else ConsoleWrite('Keine Ergebnisse' & @LF) endif  
      Select
      $SQL_table('albums') $SQL_select('id', 'Name', 'Artist', 'Song') ;or pass to an Array Local $aSelect = ['id', 'Name', 'Artist', 'Song'] $SQL_select($aSelect) $aRet = $SQL_get() if IsArray($aRet ) then _ArrayDisplay($aRet ) else ConsoleWrite('Keine Ergebnisse' & @LF) endif where
      $SQL_table('albums') $SQL_select('id', 'Name', 'Artist', 'Song', 'Votes') $SQL_where('Artist', 'adele') $SQL_where('Votes', '>=' ,'9') $SQL_orWhere('Artist', '=' ,'Rag'n'Bone Man') ;or pass to an 2dArray Local $aSelect = [['Artist','adele'],['Votes', '>=' ,'9']] $SQL_where($aSelect) $aRet = $SQL_get() if IsArray($aRet ) then _ArrayDisplay($aRet ) else ConsoleWrite('Keine Ergebnisse' & @LF) endif  
      If you need more examples, then tell me exactly what you need.
      I hope you like my UDF and find some use for it.
      ---
      ->DONWLOAD romaSQL
       
       
    • BisherSH
      By BisherSH
      Good day ,
      I have the code below , and i would like to embed SQLite3.dll to the compiled file 
      Is it possible ? 
      Thanks in advance
      #include <SQLite.au3> #include <SQLite.dll.au3> _SQLite_Startup() If @error Then     MsgBox($MB_SYSTEMMODAL, "SQLite Error", "SQLite3.dll Can't be Loaded!")     Exit -1 EndIf $DB = _SQLite_Open("C:\Temp\Test.db") $Action = "TestAction" $Time = @HOUR&":"&@MIN&":"&@SEC $Date = @YEAR&"-"&@MON&"-"&@MDAY $User = @UserName $Computer = @ComputerName $DC = @LogonServer If @error Then     MsgBox($MB_SYSTEMMODAL, "SQLite Error", "Couldnt open Database")     Exit -1 EndIf _SQLite_Exec($DB,"INSERT INTO QLogs (Action,Date,Time,User,Computer,DC) " & _                               "VALUES ("& _SQLite_FastEscape($Action) & "," & _                                           _SQLite_FastEscape($Date) & "," & _                                           _SQLite_FastEscape($Time) & "," & _                                           _SQLite_FastEscape($User) & "," & _                                           _SQLite_FastEscape($Computer) & "," & _                                           _SQLite_FastEscape($DC) & ");") If @error Then     MsgBox($MB_SYSTEMMODAL, "SQLite Error", "Couldnt insert!")     Exit -1 EndIf _SQLite_Shutdown()
    • supersonic
      By supersonic
      Hello -
      For a SQLite insert statement I'm passing a 2D array through two For/Next loops -  code snippet:
      Local $sInsertInto2 = "" For $i = 0 To $iCount - 1 $sInsertInto2 &= " (" For $j = 0 To UBound($aTmp, 2) - 2 $sInsertInto2 &= "'" & StringReplace($aTmp[$i][$j], "'", "''") & "', " Next $sInsertInto2 &= "'" & StringReplace($aTmp[$i][$j], "'", "''") & "')" & ((($iCount - 1) = $i) ? (";") : ("," & @CRLF)) Next This works great but due to StringReplace() it is very slow. StringReplace() is used to "escape" single quotes (') and it is only required if a single quote actually is present...
      Somewhere on the forum there is a faster example by UEZ but I can't find it...
      Anyone any idea?
    • FrancescoDiMuro
      By FrancescoDiMuro
      Hi guys! How are you? Hope you're fine
      I'm trying to insert a text that contains quotes in a SQLite database, and I don't know how to do.
      I tried with:
      Local $sString = "1P6AV2104'0HA04'0AA0" StringReplace($sString, "'", "''") but I didn't managed to, obtaining this error:
      --> Error:    unrecognized token: "0HA04" How can I manage to solve this problem? Thanks  
    • FrancescoDiMuro
      By FrancescoDiMuro
      Hi guys! How are you? Hope you're fine
      I'm trying to use SQLite for managing some data, and, I would like to display my "retrieved" data, but I'm trying to do a select from 2 table, and seems to not work properly...
      What I'd like to do is retrieve data from 2 tables and display in a listview...
      I tried with:
      Local $aRisultato, $iRighe, $iColonne, $iRVal $iRval = _SQLite_GetTable2d($hDatabase, "SELECT * FROM Magazzino_Rockwell, Magazzino_Siemens;", $aRisultato, $iRighe, $iColonne) If $iRVal = $SQLITE_OK Then ;_SQLite_Display2DResult($aRisultato) _ArrayDisplay($aRisultato) EndIf ... but it displays a single record 41 times, and it does this thing for every record in the database...
      What do you need to help me?
      Thanks  

      EDIT:
      Managed with a double If and double query like this:
       
      $iRval = _SQLite_GetTable2d($hDatabase, "SELECT * FROM Magazzino_Rockwell;", $aRisultato, $iRighe, $iColonne) If $iRVal = $SQLITE_OK Then Local $aRisultatoRockwell = $aRisultato $iRval = _SQLite_GetTable2d($hDatabase, "SELECT * FROM Magazzino_Siemens;", $aRisultato, $iRighe, $iColonne) If $iRVal = $SQLITE_OK Then _ArrayConcatenate($aRisultato, $aRisultatoRockwell) Local $i, $sRiga, $s_LV_Item For $i = 1 To Ubound($aRisultato) - 1 $sRiga = $aRisultato[$i][0] & "|" & _ $aRisultato[$i][1] & "|" & _ $aRisultato[$i][2] & "|" & _ $aRisultato[$i][3] & "|" & _ $aRisultato[$i][4] & "|" & _ $aRisultato[$i][5] & "|" & _ $aRisultato[$i][6] & "|" & _ $aRisultato[$i][7] & "|" & _ $aRisultato[$i][8] & "|" & _ $aRisultato[$i][9] & "|" & _ $aRisultato[$i][10] & "|" & _ $aRisultato[$i][11] $s_LV_Item = GUICtrlCreateListViewItem($sRiga, $lv_Lista) Next And so, the listview is created
      If anyone has another more efficient way, I'm here Thanks guys