I'm trying to implement a INSERT OR REPLACE SQL to update the values that come from my API, the problem is, every time that I register a new item in my API and reload the app, it is duplicating all the rows, it is inserting the whole data again, how can I prevent that to happen?
angular.forEach(item.faturamentos, function (fat) {
//debugger
db.transaction(
function (tx) {
tx.executeSql('INSERT OR REPLACE INTO faturamento_pedidos (valor_a_faturar, ' +
'nota_fiscal, ' +
'_criado,' +
'_modificado , ' +
'_status, ' +
'id_rm, ' +
'cod_id, ' +
'id_rm_pedido, ' +
'id_rm_empresa, ' +
'data, ' +
'informacoes_adicionais ) VALUES (?,?,?,?,?,?,?,?,?,?,?)',
[
fat.valor_a_faturar,
fat.nota_fiscal,
fat.criado,
fat.modificado,
fat.status,
fat.id,
fat.cod_id,
fat.id_rm_pedido,
fat.id_rm_empresa,
fat.data,
fat.informacoes_adicionais
]);
},
txErrorHandler,
function () {
log('Record inserted successfully');
}
);
});
TABLE:
tx.executeSql("CREATE TABLE IF NOT EXISTS faturamento_pedidos (" +
"faturamento_id Integer PRIMARY KEY AUTOINCREMENT, " +
"_criado Text, " +
"_modificado Text, " +
"_status Text, " +
"id_rm Integer, " +
"id_rm_pedido Integer, " +
"id_rm_empresa Integer, " +
"cod_id Text, " +
"valor_a_faturar Text, " +
"nota_fiscal Text, " +
"data Text, " +
"informacoes_adicionais Text," +
"CONSTRAINT unique_id_rm UNIQUE ('id_rm'))");
tx.executeSql('CREATE INDEX IF NOT EXISTS "faturamento_pedidos.index_faturamento_id" ON "faturamento_pedidos"("faturamento_id");');
Related
Can anyone decipher what's wrong with this method? The log says that there's is a syntax error but I'm not able to see it.
Here's the code:
public void onCreate(SQLiteDatabase sqLiteDatabase) {
String createTable = "CREATE_TABLE " + MOVIES_DB + "("
+ TITLE + " TEXT, "
+ OVERVIEW + " TEXT, "
+ POSTER_PATH + " TEXT, "
+ RELEASE_DATE + " TEXT, "
+ ORIGINAL_TITLE + " TEXT, "
+ ORIGINAL_LANGUAGE + " TEXT, "
+ BACKDROP_PATH + " TEXT, "
+ ID + " INTEGER PRIMARY KEY, "
+ VOTE_COUNT + " TEXT, "
+ POPULARITY + " TEXT, "
+ VOTE_AVERAGE + " TEXT, "
+ ADULT + " TEXT, "
+ VIDEO + " TEXT, "
+ GENRE_IDS + " TEXT, "
+ HISTORY_USER + " TEXT, "
+ WATCH_LATER + " TEXT, "
+ FAVORITE_FLAG + " INTEGER DEFAULT 0"
+ ")";
sqLiteDatabase.execSQL(createTable);
}
It used to work. I added the FAVORITE_FLAG and now it doesn't run. I also tried with INTEGER NOT NULL DEFAULT 0 after FAVORITE_FLAG
As said by #Juergen D, CREATE TABLE take a space and not and underscore.
Take a look at the CREATE TABLE Documentation for SQLite.
BTW; try to put your id / PK declaration first, as it's the common practice (and more logical)
SQL Fiddle
SQLite (SQL.js) Schema Setup:
CREATE TABLE MOVIES_DB(
"ID" INTEGER PRIMARY KEY,
"TITLE" TEXT,
"OVERVIEW" TEXT,
"POSTER_PATH" TEXT,
"RELEASE_DATE" TEXT,
"ORIGINAL_TITLE" TEXT,
"ORIGINAL_LANGUAGE" TEXT,
"BACKDROP_PATH" TEXT,
"VOTE_COUNT" TEXT,
"POPULARITY" TEXT,
"VOTE_AVERAGE" TEXT,
"ADULT" TEXT,
"VIDEO" TEXT,
"GENRE_IDS" TEXT,
"HISTORY_USER" TEXT,
"WATCH_LATER" TEXT,
"FAVORITE_FLAG" INTEGER DEFAULT 0
);
Insert into MOVIES_DB Values(1,"test","test","test 7",
"test","test 12","test","test","test","test","test",
"test","test","test","test","test",2);
Query 1:
select ID, TITLE, FAVORITE_FLAG from MOVIES_DB
Results:
| ID | TITLE | FAVORITE_FLAG |
|----|-------|---------------|
| 1 | test | 2 |
I have a table in csv file (with an ID as numeric).
I manually uploaded the information from the file to a SQL Server data table (creating my ID column as numeric).
But, I want to recreate my ID column as autonumeric ID column that continue the number with the latest entry.
Example: the table have the ID 1, 5, 10. I want to recreate the auto-incremental (IDENTITY) ID column (leaving my old ID's) and next row insertion continue with ID 11.
I suppose that doesn't exists a single method to achieve this. But I want to know the steps that I should follow.
Here is a script to give you an idea of one way you can do it.
IF OBJECT_ID('DELETEME.dbo.Tbl') IS NOT NULL
BEGIN
DROP TABLE Tbl
END
IF OBJECT_ID('DELETEME.dbo.stageTbl') IS NOT NULL
BEGIN
DROP TABLE stageTbl
END
CREATE TABLE Tbl (
ID INT
,A CHAR(1)
)
INSERT INTO Tbl VALUES (1,'A'),(2,'B'),(10,'C')
SELECT *
FROM
Tbl
EXEC sp_rename 'DELETEME.dbo.Tbl', 'stageTbl', 'OBJECT'
--renames original table
--create script for the new table
CREATE TABLE Tbl (
ID INT NOT NULL IDENTITY(1,1)
,A CHAR(1)
)
--have to set IDENTITY_INSERT on to insert the ID into an IDENTITY column
SET IDENTITY_INSERT Tbl ON
INSERT INTO Tbl (ID, A)
SELECT ID, A
FROM
stageTbl
SET IDENTITY_INSERT Tbl OFF
DROP TABLE stageTbl
--drops original table
DBCC CHECKIDENT('Tbl', RESEED, 222)
--sets the number you want to with next if you set as 222 the next identity will be 223
INSERT INTO Tbl (A) VALUES ('D')
SELECT *
FROM
Tbl
Basic Steps
Renames original Table (if you want your new table to be the same name as the old, I like to rename first due to auto generated names of constraints etc on the new table)
Create the New table with the Column as an Identity column
Turn on IDENTITY_INSERT
Select all records from the old table into the new one
Turn off IDENTITY_INSERT
You don't have to but you can RESSED the identity to start with whatever number you want otherwise SQL-server will automatically do this based on the greatest ID value.
Drop the original table that you renamed
Thanks to Matt to help me out with the original question.
I want to share a C# method that I used to automate all the necessary steps:
-- Disclaimer: the use of this is my class that connects with MS SQL Server, used to read a SELECT sentence (And returns a DataTable) and Execute SQL Queries, etc. Hope someone could find this code helpfully (AS-IS) --
/// <summary> Recreate an ID with auto-incremental when the table has the ID without this option.
/// <para>Automatically will rename the original table to TABLENAME_TO_DELETE (The process will require copy and recreate the table, then the process will duplicate the information) </para></summary>
/// <param name="strTable">SQL table</param>
/// <param name="strId">ID column</param>
public string recreateIdentityColumn(string strTable, string strId)
{
string strLog = "Table: {0} - ID: {1}".fwFormat(strTable, strId);
string strNewTable = strTable + "_" + fw.rnd(1, 1000).ToString() + fw.rnd(5000, 10000);
DataTable dtTable = this.fillDataTable("SELECT COLUMN_NAME, DATA_TYPE, NUMERIC_PRECISION, NUMERIC_SCALE " +
"FROM Information_SCHEMA.COLUMNS " +
"WHERE TABLE_NAME = '" + strTable + "'");
if (!dtTable.fwHasData()) throw new Exception("The current table '" + strTable + "' doesn't exists");
DataRow[] drIdInfo = dtTable.Select("COLUMN_NAME = '" + strId + "'");
if (!drIdInfo.fwHasData()) throw new Exception("The ID column '" + strId + "' doesn't exists in the table '" + strTable + "'");
string strIdType = "";
string strColumns = "";
strIdType = drIdInfo[0]["DATA_TYPE"].fwEmpty("");
if (strIdType.fwContains("decimal"))
strIdType += "({0}, {1})".fwFormat(drIdInfo[0]["NUMERIC_PRECISION"].ToString(), drIdInfo[0]["NUMERIC_SCALE"].ToString());
strLog += "\r\nID DataType: " + strIdType;
foreach (DataRow drInfo in dtTable.Rows)
strColumns += ",[" + drInfo["COLUMN_NAME"].ToString() + "]";
strId = "[" + strId.TrimStart('[').TrimEnd(']') + "]";
strColumns = strColumns.TrimStart(',');
strLog += "\r\nColumns: " + strColumns;
try
{
// Rule 1: Clone the table (Only the structure)
this.executeQuery("SELECT TOP 0 * INTO " + strNewTable + " FROM " + strTable);
// Rule 2: Remove the ID from the clone table
this.executeQuery("ALTER TABLE " + strNewTable + " DROP COLUMN " + strId);
// Rule 3: Add the ID column with the identity property
this.executeQuery("ALTER TABLE " + strNewTable + " ADD " + strId + " " + strIdType + " IDENTITY(1,1)");
// Rule 4: Allow manual insertion of ID in the identity column
this.executeQuery("SET IDENTITY_INSERT " + strNewTable + " ON");
// Rule 5: Copy the rows into the table
int intTotalRows = this.rowCount(strTable);
int intTotalNewRows = this.executeQuery("INSERT INTO " + strNewTable + "(" + strColumns + ") " +
"SELECT " + strColumns + " FROM " + strTable);
strLog += "\r\nOriginal rows {0} - New rows {1}".fwFormat(intTotalRows.ToString(), intTotalNewRows.ToString());
// Rule 6: Return the insertion of identity rows to a normal state
this.executeQuery("SET IDENTITY_INSERT " + strNewTable + " OFF");
// Rule 7: Rename the table with NO IDENTITY as OLD and rename the table with INDENTITY ID as NEW/ACTUAL
this.executeQuery("EXEC sp_rename '" + strTable + "', '" + strTable + "_TO_DELETE', 'OBJECT'");
this.executeQuery("EXEC sp_rename '" + strNewTable + "', '" + strTable + "', 'OBJECT'");
strLog += "\r\nProcess run without problems";
return strLog;
}
catch (Exception ex)
{
strLog += "\r\nException occur";
throw ex;
}
}
My app works like this, I have a local database that is filled with data that comes from my API, and when I have a new data inserted in my API the app checks for the last modified item and synchronize it, and in order to achieve that I'm using INSERT OR REPLACE statement, but it is messing up with my "faturamento_id", it is deleting the ids and replacing with new ones, I want it to continue auto increment(if it is possible) when there is new data to synchronize. How can I do that?
angular.forEach(item.faturamentos, function (fat) {
db.transaction(
function (tx) {
tx.executeSql('INSERT OR REPLACE INTO faturamento_pedidos (valor_a_faturar, ' +
'nota_fiscal, ' +
'_criado,' +
'_modificado , ' +
'_status, ' +
'id_rm, ' +
'cod_id, ' +
'id_rm_pedido, ' +
'id_rm_empresa, ' +
'data, ' +
'informacoes_adicionais ) VALUES (?,?,?,?,?,?,?,?,?,?,?)',
[
fat.valor_a_faturar,
fat.nota_fiscal,
fat.criado,
fat.modificado,
fat.status,
fat.id,
fat.cod_id,
fat.id_rm_pedido,
fat.id_rm_empresa,
fat.data,
fat.informacoes_adicionais
]);
},
txErrorHandler,
function () {
log('Record inserted successfully');
}
);
});
TABLE:
tx.executeSql("CREATE TABLE IF NOT EXISTS faturamento_pedidos (" +
"faturamento_id Integer PRIMARY KEY AUTOINCREMENT, " +
"_criado Text, " +
"_modificado Text, " +
"_status Text, " +
"id_rm Integer, " +
"id_rm_pedido Integer, " +
"id_rm_empresa Integer, " +
"cod_id Text, " +
"valor_a_faturar Text, " +
"nota_fiscal Text, " +
"data Text, " +
"informacoes_adicionais Text," +
"CONSTRAINT unique_id_rm UNIQUE ('id_rm'))");
tx.executeSql('CREATE INDEX IF NOT EXISTS "faturamento_pedidos.index_faturamento_id" ON "faturamento_pedidos"("faturamento_id");');
INSERT OR REPLACE always removes the old row, if it exists.
However, there is no reason to use a single SQL statement.
Just try to update the old row, and if it was not found, you know you have to insert a new one:
tx.executeSql("UPDATE ...",
[...],
function(tx, result) {
if (result.rowsAffected == 0)
tx.executeSql("INSERT ...", [...]);
});
In the following code, i want to add "IN" +Village+. Where to add this condition in the code. Variable village takes value from a drop down list based on that filter should occur.please help me.Village name is a column in my fusion table.
i.e select 'geometry',villageName from table where querypass > textvalue IN villagename='madurai'
function querymape()
{
/*variable holds the value*/
var village =document.getElementById('village').value.replace(/'/g, "\\'");
var operatore=document.getElementById('operatorstringe').value.replace(/'/g, "\\'");
var textvaluee=document.getElementById("text-valuee").value.replace(/'/g, "\\'");
var querypasse=document.getElementById('query-passe').value.replace(/'/g, "\\'");
{
layer.setQuery("SELECT 'geometry'," + querypasse + " FROM " + tableid + " WHERE " + querypasse + " " + operatore + " '" + textvaluee + "'"+"AND 'VillageName=+village+'");
}
}
/*This is my new code.But its not working.Please help me*/
function querymap()
{
//var villagename='';
var operator=document.getElementById('operatorstring').value.replace(/'/g, "\\'");
var textvalue=document.getElementById("text-value").value.replace(/'/g, "\\'");
var querypass=document.getElementById('query-pass').value.replace(/'/g, "\\'");
var searchStringe = document.getElementById('Search-stringe').value.replace(/'/g, "\\'");
{
layer.setQuery("SELECT 'geometry'," + querypass + " FROM " + tableid + " WHERE " + querypass + " " + operator + " '" + textvalue + "'"+"AND 'VillageName'="+ searchStringe+"");
}
}
Multiple conditions can be combined using the keyword "and"?
You twisted the IN syntax around, it is used when you want to match several values, if you only want to compare to a single value use "=" instead
Applied to your query (with IN syntax):
select 'geometry',villageName from table where querypass > textvalue and villagename IN ('madurai','another village')
With = syntax:
select 'geometry',villageName from table where querypass > textvalue and villagename = 'madurai'
my problem is that i have 5 tables and need inserts and selects.
what i did is for every table a class and there i wrote the SQL Statements like this
public class Contact
private static String IDCont = "id_contact";
private static String NameCont = "name_contact";
private static String StreetCont = "street_contact";
private static String Street2Cont = "street2_contact";
private static String Street3Cont = "street3_contact";
private static String ZipCont = "zip_contact";
private static String CityCont = "city_contact";
private static String CountryCont = "country_contact";
private static String Iso2Cont = "iso2_contact";
private static String PhoneCont = "phone_contact";
private static String Phone2Cont = "phone2_contact";
private static String FaxCont = "fax_contact";
private static String MailCont = "mail_contact";
private static String Mail2Cont = "mail2_contact";
private static String InternetCont = "internet_contact";
private static String DrivemapCont = "drivemap_contact";
private static String PictureCont = "picture_contact";
private static String LatitudeCont = "latitude_contact";
private static String LongitudeCont = "longitude_contact";
public static final String TABLE_NAME = "contact";
public static final String SQL_CREATE = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "(" +
IDCont + "INTEGER not NULL," +
NameCont + " TEXT not NULL," +
StreetCont + " TEXT," +
Street2Cont + " TEXT," +
Street3Cont + " TEXT," +
ZipCont + " TEXT," +
CityCont + " TEXT," +
CountryCont + " TEXT," +
Iso2Cont + " TEXT," +
PhoneCont + " TEXT," +
Phone2Cont + " TEXT," +
FaxCont + " TEXT," +
MailCont + " TEXT," +
Mail2Cont + " TEXT," +
InternetCont + " TEXT," + //website of the contact
DrivemapCont + " TEXT," + //a link to a drivemap to the contact
PictureCont + " TEXT," + //a photo of the contact building (contact is not a person)
LatitudeCont + " TEXT," +
LongitudeCont + " TEXT," +
"primary key(id_contact)" +
"foreign key(iso2)";
and my insert looks like this
public boolean SQL_INSERT_CONTACT(int IDContIns, String NameContIns, String StreetContIns,
String Street2ContIns, String Street3ContIns, String ZipContIns,
String CityContIns, String CountryContIns, String Iso2ContIns,
String PhoneContIns, String Phone2ContIns, String FaxContIns,
String MailContIns, String Mail2ContIns, String InternetContIns,
String DrivemapContIns, String PictureContIns, String LatitudeContIns,
String LongitudeContIns) {
try{
db.execSQL("INSERT INTO " + "contact" +
"(" + IDCont + ", " + NameCont + ", " + StreetCont + ", " +
Street2Cont + ", " + Street3Cont + ", " + ZipCont + ", " +
CityCont + ", " + CountryCont + ", " + Iso2Cont + ", " +
PhoneCont + ", " + Phone2Cont + ", " + FaxCont + ", " +
MailCont + ", " + Mail2Cont + ", " + InternetCont + ", " +
DrivemapCont + ", " + PictureCont + ", " + LatitudeCont + ", " +
LongitudeCont + ") " +
"VALUES (" + IDContIns + ", " + NameContIns +", " + StreetContIns + ", " +
Street2ContIns + ", " + Street3ContIns + ", " + ZipContIns + ", " +
CityContIns + ", " + CountryContIns + ", " + Iso2ContIns + ", " +
PhoneContIns + ", " + Phone2ContIns + ", " + FaxContIns + ", " +
MailContIns + ", " + Mail2ContIns + ", " + InternetContIns + ", " +
DrivemapContIns + ", " + PictureContIns + ", " + LatitudeContIns + ", " +
LongitudeContIns +")");
return true;
}
catch (SQLException e) {
return false;
}
}
i have a DBAdapter class there i created the database
public class DBAdapter {
public static final String DB_NAME = "mol.db";
private static final int DB_VERSION = 1;
private static final String TAG = "DBAdapter"; //to log
private final Context context;
private SQLiteDatabase db;
public DBAdapter(Context context)
{
this.context = context;
OpenHelper openHelper = new OpenHelper(this.context);
this.db = openHelper.getWritableDatabase();
}
public static class OpenHelper extends SQLiteOpenHelper
{
public OpenHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL(Contact.SQL_CREATE);
db.execSQL(Country.SQL_CREATE);
db.execSQL(Picture.SQL_CREATE);
db.execSQL(Product.SQL_CREATE);
db.execSQL(Project.SQL_CREATE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
Log.w(TAG, "Upgrading database from version "
+ oldVersion + " to " + newVersion
+ ", which will destroy all old data");
db.execSQL(Contact.SQL_DROP);
db.execSQL(Country.SQL_DROP);
db.execSQL(Picture.SQL_DROP);
db.execSQL(Product.SQL_DROP);
db.execSQL(Project.SQL_DROP);
onCreate(db);
}
i found so many different things and tried them but i didn't get anything to work...
i need to know how can i access the database in my activity
and how i can get the insert to work
and is there sth wrong in my code?
thanks for your help
thats how i tried to get it into my activity
public class MainTabActivity extends TabActivity {
private Context context;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.maintabactivity);
TabHost mTabHost = getTabHost();
Intent intent1 = new Intent().setClass(this,MapOfLight.class);
//Intent intent2 = new Intent().setClass(this,Test.class); //Testactivity
//Intent intent2 = new Intent().setClass(this,DetailView.class); //DetailView
Intent intent2 = new Intent().setClass(this,ObjectList.class); //ObjectList
//Intent intent2 = new Intent().setClass(this,Gallery.class); //Gallery
Intent intent3 = new Intent().setClass(this,ContactDetail.class);
mTabHost.addTab(mTabHost.newTabSpec("tab_mol").setIndicator(this.getText(R.string.mol), getResources().getDrawable(R.drawable.ic_tab_mol)).setContent(intent1));
mTabHost.addTab(mTabHost.newTabSpec("tab_highlights").setIndicator(this.getText(R.string.highlights),getResources().getDrawable(R.drawable.ic_tab_highlights)).setContent(intent2));
mTabHost.addTab(mTabHost.newTabSpec("tab_contacts").setIndicator(this.getText(R.string.contact),getResources().getDrawable(R.drawable.ic_tab_contact)).setContent(intent3));
mTabHost.setCurrentTab(1);
SQLiteDatabase db;
DBAdapter dh = null;
OpenHelper openHelper = new OpenHelper(this.context);
dh = new DBAdapter(this);
db = openHelper.getWritableDatabase();
dh.SQL_INSERT_COUNTRY("AT", "Austria", "AUT");
}
}
i tried it with my country table because it has only 3 columns
public class Country {
private static String Iso2Count = "iso2_country";
private static String NameCount = "name_country";
private static String FlagCount = "flag_image_url_country";
public static final String TABLE_NAME = "country";
public static final String SQL_CREATE = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "(" +
Iso2Count + " TEXT not NULL," +
NameCount + " TEXT not NULL," +
FlagCount + " TEXT not NULL," +
"primary key(iso2_country)";
public boolean SQL_INSERT_COUNTRY(String Iso2CountIns, String NameCountIns, String FlagCountIns) {
try{
db.execSQL("INSERT INTO " + "country" +
"(" + Iso2Count + ", " + NameCount + ", " + FlagCount + ") " +
"VALUES ( " + Iso2CountIns + ", " + NameCountIns +", " + FlagCountIns + " )");
return true;
}
catch (SQLException e) {
return false;
}
}
another question is it better to put the insert and select from each table into a separate class, so i have 1 class for each table or put them all into the DBAdapter class?
EDIT: I'm not sure you have shown all your code and therefore I'm not sure my answer is helpful. Where do you declare the variables IDCont, NameCont, StreetCont ... ? I assume they are constants defining the names of your fields. In which case my answer is not correct as that should form a valid INSERT statement.
Can you add the error messages you are seeing as well as being more specific on the DB server you are using?
Your INSERT statement will not work because you are inserting the values of the variables passed to the function, instead of specifying the names of the columns.
The first part of the statment should be all one string:
"INSERT INTO contact (IDCont, NameCont, StreetCont, Street2Cont, Street3Cont, ZipCont," +
"CityCont, CountryCont, Iso2Cont, PhoneCont, Phone2Cont, FaxCont, MailCont, " +
"Mail2Cont, InternetCont, DrivemapCont, PictureCont, LatitudeCont, LongitudeCont) "
"VALUES ("IDContIns + ", " + NameContIns +", " + StreetContIns + ", " +
Street2ContIns + ", " + Street3ContIns + ", " + ZipContIns + ", " +
CityContIns + ", " + CountryContIns + ", " + Iso2ContIns + ", " +
PhoneContIns + ", " + Phone2ContIns + ", " + FaxContIns + ", " +
MailContIns + ", " + Mail2ContIns + ", " + InternetContIns + ", " +
DrivemapContIns + ", " + PictureContIns + ", " + LatitudeContIns + ", " +
LongitudeContIns +")"
I would also question your table design, why are most of the fields TEXT and not a more appropriate data type?