I have a very simple MySQL Table and want to select some of the rows using QSqlQuery.
I am connected to my local development mysql server (Windows; 64-bit).
When I run a SELECT query with other tools like mysql workbench, I always get the correct results (of course!).
Doing the same with QSqlQuery gives me no rows at all!
QString sql = "SELECT `ID`, `Name`, `ModbusID`, `DeviceType` FROM `Devices`;";
qDebug() << sql;
QSqlQuery query(m_db);
if(!query.prepare(sql))
{
qFatal("could not prepare query");
return;
}
if(!query.exec())
{
qFatal("could not execute query");
return;
}
while(query.next())
qDebug() << "result";
qDebug() << "finished.";
SQL-Table Definition
CREATE TABLE IF NOT EXISTS `Devices` (
`ID` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`MeasurementID` INT UNSIGNED NOT NULL,
`Name` VARCHAR(255) NOT NULL,
`ModbusID` TINYINT UNSIGNED NOT NULL,
`DeviceType` INT NOT NULL,
`TimestampCreated` DATETIME NOT NULL,
`TimestampLastModified` DATETIME,
FOREIGN KEY(`MeasurementID`) REFERENCES `Measurements`(`ID`) ON DELETE CASCADE,
UNIQUE (`MeasurementID`, `Name`)
);
In both programs I am connected to the same local mysql instance. There are no other mysql servers on my machine or on the network.
This happens with Oracle's MySQL and MariaDB! So the problem must be in my program.
Am I doing something wrong or what's happening here?
UPDATE After multiple tests the problem only occurs when I select ModbusID. I changed the table definition from
`ModbusID` TINYINT UNSIGNED NOT NULL,
to
`ModbusID` INT UNSIGNED NOT NULL,
and now it works. Looks like a bug in QT. But I dont think that this is a good solution. If you know a way to use TINYINT then please write an answer or comment!
Related
I use the C++ connector for MySQL and the X dev API code.
On my test server (my machine), doing a single insert in loop is pretty slow (about 1000 per second) on a basic table with a few columns. It has a unique index on a char(40) field which is possibly the cause of the slowness. But since the DB is configured as developer mode, I guess this should be expected.
I wanted to improve this by doing batch inserts. The problem is that it is even slower (about 20 per second). The execute() itself is quite fast, but the .values() are extremely slow. The code looks something like this:
try
{
mysqlx::TableInsert MyInsert = m_DBRegisterConnection->GetSchema()->getTable("MyTable").insert("UniqueID", "This", "AndThat");
for (int i = 0; i < ToBeInserted; i++)
{
MyInsert = MyInsert.values(m_MyQueue.getAt(i)->InsertValues[0],
m_MyQueue.getAt(i)->InsertValues[1],
m_MyQueue.getAt(i)->InsertValues[2]);
}
MyInsert.execute();
}
catch (std::exception& e)
{
}
Here is the table create:
CREATE TABLE `players` (
`id` bigint NOT NULL AUTO_INCREMENT,
`UniqueID` char(32) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL,
`PlayerID` varchar(500) DEFAULT NULL,
`Email` varchar(255) DEFAULT NULL,
`Password` varchar(63) DEFAULT NULL,
`CodeEmailValidation` int DEFAULT NULL,
`CodeDateGenerated` datetime DEFAULT NULL,
`LastLogin` datetime NOT NULL,
`Validated` tinyint DEFAULT '0',
`DateCreated` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UniqueID_UNIQUE` (`UniqueID`)
) ENGINE=InnoDB AUTO_INCREMENT=21124342 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
Any clue why this is much slower? Is there a better way to do a batch insert?
The issue is in your code.
MyInsert = MyInsert.values(m_MyQueue.getAt(i)->InsertValues[0],
m_MyQueue.getAt(i)->InsertValues[1],
m_MyQueue.getAt(i)->InsertValues[2]);
You are copying over and over again the MyInsert object to a temporary and restroying it....
Should only be:
MyInsert.values(m_MyQueue.getAt(i)->InsertValues[0],
m_MyQueue.getAt(i)->InsertValues[1],
m_MyQueue.getAt(i)->InsertValues[2]);
However, since this could be prevented on the connector code, I'll report a bug to fix the copy behavior.
INSERT up to 1000 rows in a single INSERT statement. That will run 10 times as fast.
Is that CHAR(40) some form of UUID or Hash? If so, would it be possible sort the data before inserting? That may help it run faster. However, please provide SHOW CREATE TABLE so I can discuss this aspect further. I really need to seen all the indexes and datatypes.
I've created a MySQL Model with a few tables, some of them with fk's to another table. I usually export the SQL from MySQL Model to my database using the "Forward Engineer SQL CREATE Script" inside File -> Export -> Forward Engineer SQL CREATE Script. The problem here is that when I generate the creation script, all my fk's become unique. I didn't check UQ option in MySQL Model but it creates a script with unique fk's anyway, so, I need to change the SQL file generated and remove all the unwanted uniques. Anyone has a clue why this is happening?
Generated script:
CREATE TABLE IF NOT EXISTS `u514786799_detranleiloes`.`Lotes` (
`createdAt` DATE NOT NULL,
`updatedAt` DATE NOT NULL,
`id` INT UNIQUE NOT NULL AUTO_INCREMENT,
`LeiloesId` INT UNIQUE NOT NULL,
`conservado` TINYINT NULL,
`numero` INT NOT NULL,
`CRDsId` INT UNIQUE NULL,
PRIMARY KEY (`id`),
INDEX `fk_Lotes_Leiloes_idx` (`LeiloesId` ASC),
INDEX `fk_Lotes_CRDs1_idx` (`CRDsId` ASC),
CONSTRAINT `fk_Lotes_Leiloes`
FOREIGN KEY (`LeiloesId`)
REFERENCES `u514786799_detranleiloes`.`Leiloes` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_Lotes_CRDs1`
FOREIGN KEY (`CRDsId`)
REFERENCES `u514786799_detranleiloes`.`CRDs` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
AUTO_INCREMENT = 1;
I have written a QT GUI application that connects to an Oracle Database and performs query and shows the output in a QTableView.
QString host_name=ui->lineHostName->text();
QString db_name=ui->lineDatabaseName->text();
QString user_name=ui->lineUserName->text();
QString pass_word=ui->linePassword->text();
QString port_no=ui->linePortNumber->text();
QSqlDatabase db = QSqlDatabase::addDatabase("QOCI");
db.setHostName(host_name);
db.setDatabaseName(db_name);
db.setUserName(user_name);
db.setPassword(pass_word);
db.setPort(port_no.toInt());
QString MyQuery = ui->lineQuery->text();
db.open();
QSqlQuery query(MyQuery,db);
if(query.exec())
{
this->model=new QSqlQueryModel();
model->setQuery(MyQuery);
ui->tableViewOra->setModel(model);
}
After running the program, I tried to use this (as a substitute of the DESC )---
SELECT
column_name "Name",
nullable "Null?",
concat(concat(concat(data_type,'('),data_length),')') "Type"
FROM user_tab_columns
WHERE table_name='my_table_number_one';
And the column names, null parameter and data type was shown on the QTableView
Now my question is, can I use this information in the QTableView to create another table with same Column names and data type ??? (Basically creating a copy of my queried table table).
EDIT
After suggestions i tried modifying with---
QString query_to_replicate;
query_to_replicate=QString("CREATE OR REPLACE TABLE %1 AS %2").arg("AJ_REPLACEMENT_TESTING").arg(ui->lineEdit->text());
QSqlQuery query_second(query_to_replicate,db);
if(query_second.exec())
{
ui->r_pop_Button->setStyleSheet("QPushButton {background-color: rgb(0, 255, 0);}");
this->model_relocate=new QSqlQueryModel();
model_relocate->setQuery(query_second);
ui->tableView2->setModel(model_relocate);
while (model_relocate->canFetchMore())
model_relocate->fetchMore();
qDebug()<<QDateTime::currentDateTime()<<"Query SUCCESS ";
db.close();
}
now it worked twice, without throwing errors and created replicated copies in the oracle database (I used different names for replicated table before building).
But after running successfully twice, it seized replicating. Situation is completely clueless. I am not getting any errors during build / compile time.
You can do this by using CREATE TABLE AS SELECT:
QString sql = "CREATE TABLE %1 AS %2"
.arg(yourNewTableName)
.arg(ui->lineQuery->text());
// and execute this sql code on your QSqlDatabase as you do it above
It will create new table, with name from "yourNewTableName" variable and copy data from select query to new table.
Code update:
QString query_to_replicate;
query_to_replicate=QString("CREATE OR REPLACE TABLE %1 AS %2").arg("AJ_REPLACEMENT_TESTING").arg(ui->lineEdit->text());
QSqlQuery query_second(query_to_replicate,db); // query will be executed there! weird, but...
if (query_second.lastError().isValid())
{
qDebug() << query_second.lastError().text(); // error happens
}
else
{
qDebug() << "Table created successfully";
}
Also, you must #include <QSqlError> in the top of file, to use QtSql errors.
I have a table my_table with fields
id, INT, auto_increment
field_one, varchar(64)
field_two, tinytext
field_three, longblob
when trying to insert I use the following code
sql::PreparedStatement *prepared_statement = this->connection_->prepareStatement("INSERT INTO my_table(field_one,field_two,field_three) VALUES ('one','two',?)");
std::ifstream file_stream("myfile");
prepared_statement->setBlob(3, &file_stream);
I get MySQL_Prepared_Statement::setBlob: invalid 'parameterIndex'
this->connection_ is valid, the prepared_statement is not NULL, and the file stream is open
documentation on the connector classes seems lacking.
any suggestions?
Thank You!
I am trying to make a page where i handle my invoces. I have the invoice data in one tables and the invoice rows in another table. The tables looks as follows:
CREATE TABLE IF NOT EXISTS `Invoices` (
`I_Id` int(10) NOT NULL AUTO_INCREMENT,
`I_Number` int(4) NOT NULL,
`I_ClientId` int(10) NOT NULL,
`I_ExtraText` text NOT NULL,
PRIMARY KEY (`I_Id`)
) ENGINE=InnoDB
CREATE TABLE IF NOT EXISTS `InvoiceRows` (
`IR_Id` int(10) NOT NULL AUTO_INCREMENT,
`IR_InvoiceId` int(10) NOT NULL,
`IR_Price` int(10) NOT NULL,
`IR_Vat` smallint(2) unsigned NOT NULL,
`IR_Quantity` int(10) NOT NULL,
`IR_Text` varchar(255) NOT NULL,
PRIMARY KEY (`IR_Id`),
KEY `IR_InvoiceId` (`IR_InvoiceId`)
) ENGINE=InnoDB
Here is my mapping:
class Invoice {
/**
* #ORM\OneToMany(targetEntity="Row", mappedBy="invoice" ,cascade={"persist"})
*/
protected $rows;
}
class Row {
/**
* #ORM\ManyToOne(targetEntity="Invoice", inversedBy="rows", cascade={"persist"})
* #ORM\JoinColumn(name="IR_InvoiceId", referencedColumnName="I_Id")
**/
private $invoice;
}
I have been trying to follow the example at the doctrine docs on how to setup a One-To-Many, Bidirectional mapping. This is then connect with Zend Framework 2 and form collections. Pulling data works very good. I get all the rows of each invoice.
My Problem is when i want to write back to the database and save my changes. When i try to save i get the following error:
An exception occurred while executing 'INSERT INTO
MVIT_ADM__InvoiceRows (IR_InvoiceId, IR_Price, IR_Vat, IR_Quantity,
IR_Text) VALUES (?, ?, ?, ?, ?)' with params
{"1":null,"2":320,"3":0,"4":1,"5":"Learning your dog to sit"}:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column
'IR_InvoiceId' cannot be null
What have i done wrong? When checking the data from the post value is not empty.
Edit: Full source can be found at Github
It seems IR_InvoiceId null, it expect the Id of Invoices (I_Id) value, so make sure while you are inserting the data in InvoiceRows table then here pass the Invoices (I_Id) value as IR_InvoiceId as you mention table relation..
Best Of Luck!
Saran