Default DB values during inserting new record to QSqlTableModel - qt

How to insert new record to QSqlTableModel with respect to default values of DB?
UPD:
I am trying to call pTableModel->insertRecord(0, pTableModel->record(0));
or pTableModel->insertRecord(0, pTableModel->record());
or pTableModel->insertRecord(QSqlDatabase::database().record("tableName"));
or pTableModel->insertRow(0);
Result the same, all fields are NULL instead of default values of DB.

The fact that you're inserting at row 0 may be an issue. When I've tried doing that, I don't get the record I expect when I later ask for the record at row 1 (which is where the inserted record should be after a call of insertRecord(0, ...)). Also, are you calling pTableModel->submit() or pTableModel->submitAll()? If not, your record never gets committed to the database.
This code works for me:
QSqlRecord rec( pTableModel->record() );
// Insert at end of table
pTableModel->insertRecord( -1, rec );
pTableModel->submitAll();
// Or, pTableModel->submit(), depending on the model's edit strategy
// Grab the last row. It should be the one just inserted.
QSqlRecord writtenRec( pTableModel->record( pTableModel->rowCount() - 1 ) );

Related

how to pass current row into a oracle user defined function

I want to create an inline oracle function which will refer the column values of the current row being fetched and to return a value as per my conditions. I tried the same by passing ROWID into function and in the function body current row will be fetched using ROWID and manipulate the values.
CREATE FUNCTION CHECK_STATUS(P_ROWID) RETURN VARCHAR2 IS
V_ROW MY_TBL%TYPE
BEGIN
SELECT * INTO V_ROW FROM MY_TBL WHERE ROWID=P_ROWID;
IF V_ROW.COL1 IS NOT NULL AND
V_ROW.COL2 IS NOT NULL AND
V_ROW.COL3 IS NOT NULL THEN
RETURN 'OK';
ELSE
RETURN 'INCOMPLETE';
END IF;
END;
This function is further called at various places as
SELECT A.*,CHECK_STATUS(ROWID) FROM MY_TBL A;
it works but slows down the query badly over a thousand records because on each fetch of rows function will again do a select query for getting the column values. I know that this can also be done as
CREATE FUNCTION CHECK_STATUS(COL1,COL2,COL3) RETURN VARCHAR2 IS
here the problem is that i want to nearly check 9 column values in the function and it looks odd to write the column name during every call of the function. I doubt is there any method that the function can refer the current row being fetched without receiving ROWID/ COLUMNS through parameter something like (THIS.COL1,THIS.COL2,THIS.COL3)
You could add a virtual column for this, using a case expression, and not have a function at all:
alter table my_tbl add (status generated always as
(case when column1 is null or column2 is null or column3 is null
-- etc., all 9 columns or whatever else you want to check
then 'INCOMPLETE' else 'OK' end) virtual);
You can then query it with:
select column1, column2, ..., status from my_tbl
You can also add an index on the virtual column if that's useful for how you'll use it.
You could still use a (deterministic) function if you wanted to, with all the column values passed in - the 'looks odd' part would be hidden in the DDL, so queries wouldn't see it. It doesn't sound like using a function would add much in this case though.

Incorrect default value passed to the SQL Server database

I have set my column to int not null default 1... but whenever I save my record, it sets default value for that record to be 0.
I am not setting it anywhere. I don't know where I am making a mistake.
I have debugged my code , and when I am passing new entity object it is setting default value for not null to 0 .May be it is something with LINQ, But I don't know how to handle it.I don't want to explicitly assign value.
Thanks!
For sql-server, you can use SQL Server Profiler to catch all the scripts you run into the DB.
This may show you some details
Try running this query, replacing the 'myTable' and 'myColumn' values with your actual TABLE and COLUMN names, and see what's returned:
SELECT
OBJECT_NAME(C.object_id) AS [Table Name]
,C.Name AS [Column Name]
,DC.Name AS [Constraint Name]
,DC.Type_Desc AS [Constraint Type]
,DC.Definition AS [Default Value]
FROM sys.default_constraints DC
INNER JOIN sys.Columns C
ON DC.parent_column_id = C.column_id
AND DC.parent_object_id = C.object_id
WHERE OBJECT_NAME(DC.parent_object_id) = 'myTable'
AND COL_NAME(DC.parent_object_id,DC.parent_column_id) = 'myColumn'
;
Should return something like this:
[Table Name] [Column Name] [Constraint Name] [Constraint Type] [Default Value]
-------------------------------------------------------------------------------------------
myTable myColumn DF_myTable_myColumn DEFAULT_CONSTRAINT ('0')
If the [Default Value] returned is indeed (1), then it means that you have set the constraint properly and something else is at play here. It might be a trigger, or some other automated DML that you've forgotten/didn't know about, or something else entirely.
I am not the world's biggest fan of using a TRIGGER, but in a case like this, it could be handy. I find that one of the best uses for a TRIGGER is debugging little stuff like this - because it lets you see what values are being passed into a table without having to scroll through mountains of profiler data. You could try something like this (again, switching out the myTable and myColumn values with your actual table and column names):
CREATE TABLE Default_Check
(
Action_Time DATETIME NOT NULL DEFAULT GETDATE()
,Inserted_Value INT
);
CREATE TRIGGER Checking_Default ON myTable
AFTER INSERT, UPDATE
AS
BEGIN
INSERT INTO Default_Check (Inserted_Value)
SELECT I.myColumn
FROM Inserted I
;
END
;
This trigger would simply list the date/time of an update/insert done against your table, as well as the inserted value. After creating this, you could run a single INSERT statement, then check:
SELECT * FROM Default_Check;
If you see one row, only one action (insert/update) was done against the table. If you see two, something you don't expect is happening - you can check to see what. You will also see here when the 0 was inserted/updated.
When you're done, just make sure you DROP the trigger:
DROP TRIGGER Checking_Default;
You'll want to DROP the table, too, once it's become irrelevant:
DROP TABLE Default_Check;
If all of this still didn't help you, let me know.
In VB use
Property VariableName As Integer? = Nothing
And
In C# use
int? value = 0;
if (value == 0)
{
value = null;
}
Please check My Example:
create table emp ( ids int null, [DOJ] datetime NOT null)
ALTER TABLE [dbo].[Emp] ADD CONSTRAINT DF_Emp_DOJ DEFAULT (GETDATE()) FOR [DOJ]
1--Not working for Default Values
insert into emp
select '1',''
2 ---working for Default Values
insert into emp(ids) Values(13)
select * From emp

Insert/update trigger updating column value of all rows

I am running into a logical problem.My Trigger is:
create trigger Points1
on Posts
after insert, update
As
declare #value int
declare #postedby int
select #value= Count(Message) from Posts
select #postedby = PostedBy from Posts
update AspNetUsers set User_points = #value * 3
where ( AspNetUsers.Id = #postedby)
I dont know whether i am doing it right or not.
Two tables: AspNetUsers table with User_points column and Id Column as primary key
Posts table with PostId as primary key and PostedBy as foreign key referencing the AspNetUsers table.
Now, i want to compare PostedBy with Id column and if they both are same then update the User_Points column with +3 on every single message he posted.
Now, problem is:
1> It is inserting same number of points in every Row.It should check only currently inserted row and the PostedBy column of that row and then compare with Id column of other table and should Update user's Point of only that Id.
But same result nothing happens
Please tell me how to do it.
thanks in advance
change
select #postedby = PostedBy from Posts
to
select #postedby = PostedBy from INSERTED
'INSERTED' is a magic table that keep insert/updated data in this scope.
Same as this 'DELETED' table keep previous data in update a row

How to delete a row that has the same ID as a variable in an SQLite database

I've got a function that I'd like use to delete a row in my database. This is the only way I've used the DELETE statement to remove a row before but I want the 1 to be replaced by a variable called recID so that the value of recID is the row ID number which is deleted. So if recID = 6, I want the function to delete the row with ID = 6. I hope that makes sense.
'DELETE FROM MyRecords WHERE ID=1';
The notation I've been using is the following, if it helps or makes any difference.
db.transaction(function(transaction) {
transaction.executeSql( //DELETE STATEMENT HERE );
});
executeSql supports arguments (check definition).
Use it like:
db.transaction(function(transaction) {
transaction.executeSql("DELETE FROM MyRecords WHERE ID=?", [recId]);
});
If you're certain that your variable, recID, will only ever contain numbers, you can just use:
transaction.executeSql("DELETE FROM MyRecords WHERE ID=" + recID);
If recID comes from outside your application (user input) however, it either needs to be sanitized, or use a prepared statement and use the database API to set the parameter after the statement has been prepared. Otherwise you open yourself up to SQL injection attacks.
I don't know the details of your SQLite wrapper, or what version of SQLite it wraps, but creating a prepared statement using the SQLite3 C API would go something like this:
// sqlite3* db = ...
sqlite3_stmt* stmt;
sqlite3_prepare_v2(db, "DELETE FROM MyRecords WHERE ID=?", -1, &stmt, 0);
sqlite3_bind_int(stmt, 1, recID);
sqlite3_step();
// ...
sqlite3_finalize(stmt);
This simple example excludes all the error checking you'd want to do in a real application, but since you're using a wrapper that has different syntax anyway, you'd have to figure out how it wraps these functions anyway.

How to get the ID of a previously inserted row within a transaction using QSqlQuery

I am trying to get the primary key of an inserted row within a transaction scope, because I do not want to leave the db in a logically inconsistent state.
My problem is I cannot find a way to retrieve the ID value of a previously executed query, which I want to use for the next insert query. Querying the PostgreSQL database while the transaction is in effect shows no results in the non-foreign-key table(the row is not yet committed?). I believe this is due to the transaction's isolation level.
Below is what I'm trying to do with production code, albeit slightly edited and narrowed down to one function for clarity. const int lastInsertId is always 0, which in this context should mean no value was found (technically that toInt() function failed). I tried manually inserting a valid non-foreign-key row, and then calling LASTVAL() which produced the expected result - the ID of the inserted row.
So, what am I doing wrong? What am I missing or misunderstanding here?
void createEntityWithoutForiegnKeyConstraint(const QString &nameOfEntity)
{
db_.transaction();
QSqlQuery insertQuery(db_);
insertQuery.prepare("INSERT INTO \"EntityWithoutForeignKey\" (\"name\") VALUES (:name);");
insertQuery.bindValue(":name", nameOfEntity);
execQuery(__LINE__, insertQuery);
QSqlQuery lastIdQuery("SELECT LASTVAL();", db_); // auto executes
const int lastInsertId = lastIdQuery.value(0).toInt();
if (lastInsertId <= 0) // 0 is not a valid ID
throw exception("Oh noes.");
createEntityWithForeignKeyConstraint(lastInsertId, someData);
if (!db_.commit())
db_.rollback();
}
I realise this is an old question but in Qt 5.10 (and likely earlier) there is a function QSqlQuery::lastInsertId() which can be called after QSqlQuery::exec().
It's quite useful if you are using a database such as SQLite which doesn't support the RETURNING clause on an INSERT statement.
QSqlQuery::lastInsertId() documentation.
Usage is something along the lines of the following:
QSqlQuery q;
q.prepare("INSERT INTO table_name VALUES(:some_column_name)");
q.bindValue(":some_column_name", "FooBar");
q.exec();
qDebug() << "Last ID was:" << q.lastInsertId();
#Kasheen is perfectly right but I want to set the focus on one important aspect you should keep in mind: Don't forget to encapsulate everything in one single transaction.
Why? It saves time and avoids database corruption if the second insert using the generated primary key (you got with q.lastInsertId()) fails.
So your insert should look like this (this is basically #Kasheen's answer with some additions):
db_.transaction(); // Starts a transaction
QSqlQuery q;
// first insert
q.prepare("INSERT INTO table_name VALUES(:some_column_name)");
q.bindValue(":some_column_name", "FooBar");
q.exec();
auto pk == q.lastInsertId().toInt;
// second insert
q.prepare("INSERT INTO other_table VALUES(:other_column_name, :fk)");
q.bindValue(":other_column_name", "OtherText");
q.bindValue(":fk", pk);
q.exec();
db_.commit(); // Commits transaction
#average joe does the transaction handling correctly but you might forget it if you look on the solution only.

Resources