Firstly, I apologise if this is a really stupid question.
I had a question about dealing correctly with SQL statements within Yii. I'll make a small example code.
public function actionCreate($id) {
$cmd = Yii::app()->db->createCommand();
$cmd->insert('table_1',array(
'user_id'=> (int) $id,
),'id=:id', array(':id'=>$id));
}
What's the correct way to confirm this query worked? Is it try/catch blocks?
The reason I ask is that could fail if it's passed a bad parameter, but on a couple of tables I have DB constraints that could also result in a failure, so I wanted to try and make sure I handled everything properly rather than blanket handle them.
From official document
Executing SQL Statements Once a database connection is established, SQL statements can be executed using CDbCommand. One
creates a CDbCommand instance by calling
CDbConnection::createCommand() with the specified SQL statement:
$connection=Yii::app()->db; // assuming you have configured a "db" connection
// If not, you may explicitly create a connection:
// $connection=new CDbConnection($dsn,$username,$password);
$command=$connection->createCommand($sql);
// if needed, the SQL statement may be updated as follows:
// $command->text=$newSQL;
A SQL statement is executed via CDbCommand in one of the following two ways:
And here it is
execute(): performs a non-query SQL statement, such as INSERT, UPDATE
and DELETE. If successful, it returns the number of rows that are
affected by the execution.
Btw, insert() is a low level method that's used internally by Active Record (AR). Why don't you simply use AR instead
By Yii gii, you automatically get model for table_1, and you can find, insert, update, delete from that. Example:
$model = new Table1ModelName;
$model->user_id= $id;
$model->name= $user_name;
...
$model->save();
There still has many workarounds and interesting things which you would like to study about
Yii Working Active Record
Related
I'm trying to commit DML update in a database table while the main program is still running without committing it as there may be errors in future and there might be a need to rollback it but the internal (saved) updates should stay.
Like in the Oracle autonomous transactions.
Call function ... starting new task ... or Submit ... and return don't work as they affect the main transaction.
Is there a way to start a nested database LUW and commit it without interrupting the main LUW?
I am not aware of a way to do this with OpenSQL. But when you are using the ADBC framework, then each instance of the class CL_SQL_CONNECTION operates within a separate database LUW.
I would generally not recommend using ADBC unless you have to, because:
You are now writing SQL statements as strings, which means you don't have compile-time syntax checking.
You can't put variables into SQL code anymore. (OK, you can, but you shouldn't, because you are probably creating SQL injection vulnerabilities that way). You need to pass all the variables using statement->set_param.
You are now writing NativeSQL, which means that you might inadvertently write SQL which can't be ported to other database backends.
You can create separate function for saving your changes and you can call your function with starting new task mode like below.
call function 'ZFUNCTION' starting new task 'SAVECHANGES'
exporting
param = value.
I am working on executing a set of update queries which are dynamically generated to be executed on SQL Server using iBatis2. I have written update element in sqlMap as below which executes within scope of a transaction :
<update id="updateDepartments" parameterClass="Office">
declare #sql nvarchar(400);
<iterate property="departmentList">
<!-- form the update query and store in #sql-->
exec sp_executesql #sql
</iterate>
</update>
I have a couple of questions related to the way above queries execute.
Do they execute as a batch or individually i.e. does the number of network calls to database server are equal to the number of update queries generated ?
How can the client code know how many rows actually got updated if the queries execute ? The return value shows as 1 always even though multiple rows got updated.
Is there a better way to do this using iBatis2 ?
Example of Dynamic update queries formed are:
update Department set cost1=1000 where department_name='sales'
update Department set cost2=2000 where department_name='finance'
update Department set cost3=3000 where department_name='marketing'
Parameters passed as part of paramterClass are List of objects containing:
1. Department name
2. Column name to be updated
3. Value to be updated for column in 2.
example,
['sales', 'cost1', 1000]
['finance', 'cost2', 2000]
It may be possible to perform this as a batch execution but I'm not positive it can be. I haven't used iBatis 2 in a long time now.
What I'm sure will work is executing each SQL statement separately. There's pretty much no overhead in calling it multiple times, unless you are performing thousands of updates at once. Are you?
I think you could call is each time using a parameter class like:
class updateDptParams {
String name;
String column;
String value;
// setters & getters omitted for brevity
}
Then, the mapper could look like:
<update id="updateDepartment" parameterClass="updateDptParams">
update Department set ${column}=${value} where department_name=#{name}
</update>
Note that column and value are injected as strings (using ${}), since they are supposed to have variable types. However, name is a standard iBatis JDBC parameter (using #{}) since it's always a VARCHAR. Make sure injected parameters come from a known source, and not from the user interface or other external source; otherwise your code will be vulnerable to SQL Injection.
Finally, if you are updating thousands of rows, this solution can still be good. It could be improved batching updates, or performing multiple updates at once using complex SQL statements. I'm not sure how easy or error-prone this potential optimization could be, though.
I issue SP from Jsp, code is here:
sql = "EXEC REP_INVOICES ?,?";
java.sql.PreparedStatement ps = cox.prepareStatement(sql);
ps.setEscapeProcessing(true);
ps.setInt(1, cycle);
ps.setInt(2, zone);
ps.execute();
Procedure runs several seconds and fills a table. I want to know when it is over to make outputs. Is it possible?
I has been ages since I did java.
However, there is JDBC and SQL libraries.
I think you are using the first. Here is a link to execute().
http://docs.oracle.com/javase/6/docs/api/java/sql/PreparedStatement.html
I guess the main question is this statement modal? After the execute() does the java wait until the call is finished? I think so.
Have the stored procedure return a value. Check it. After that, you whole table should be populated.
The only other alternative is to do paging. Load only a few records in the table at a time. Should produce quicker response times.
Here is the definition from the manual on return values and how to get them from a SPROC call.
execute
boolean execute()
Executes the SQL statement in this PreparedStatement object, which may be any kind of SQL
statement. Some prepared statements return multiple results; the execute method handles these
complex statements as well as the simpler form of statements handled by the methods
executeQuery and executeUpdate.
The execute method returns a boolean to indicate the form of the first result. You must call
either the method getResultSet or getUpdateCount to retrieve the result; you must call
getMoreResults to move to any subsequent result(s).
I have an entity with Id column generated using Hilo.
I have a transaction, creating a new entity and calling SaveOrUpdate() in order to get the Hilo generated Id of the entity (I need to write that Id to another DB).
later on, within the same transaction I update the new entity, just a simple update of a simple property, and in the end I call SaveOrUpdate() again.
I see that the SQL commands generated are first INSERT and then an UPDATE, but what I want is just an INSERT with the final details of the entity. is that possible? am I doing something wrong?
EDIT: added code sample
here's a very simplified example of pseudo code:
Person newPerson = new Person(); // Person is a mapped entity
newPerson.Name = "foo";
_session.SaveOrUpdate(newPerson); // generates INSERT statement
newPerson.BirthDate = DateTime.Now;
_session.SaveOrUpdate(newPerson); // generates UPDATE statement
// assume session transaction was opened before and disposed correctly for sake of simplicity
_session.Transaction.Commit();
The point is that with ORM tools like NHibernate, we are working different way, then we did with ADO.NET.
While ADO.NET Commands and their Execute() method family would cause immediate SQL statement execution on the DB server... with NHibernate it is dramatically different.
We are working with a ISession. The session, could be thought as a C# collection in a memory. All the Save(), SaveOrUdpate(), Update(), Delete() ... calls are executed against that object representation. NO SQL Command is executed, when calling these methods, no low-level ADO.NET calls at the moment.
That abstraction allows NHibernate to optimize the final SQL Statement batch... based on all the information gathered in the ISession. And that's why, you will never see INSERT, UPDATE if working with one Session, unless we explictly call the magical Flush() or change the FlushMode at all.
In that case (calling Flush() ), we are trying to say: NHibernate we are smart enough, now is the time to execute commands. In other scenarios, usually it is good enough to leave it on NHibernate...
See here:
- 9.6. Flush
ASP.NET 2.0, SQL 2005. I have a very basic insert statement. I enter all the data into the app and step through. No errors are rasied in the app or the stored proc. Yet, when I go to check out the table, no record was inserted. Is there some sort of quirk or bug in SQL server I am unaware of? I have tried ExecuteScalar & ExecuteNonQuery.
Can it be that you open a transaction and never Commit one? Remember that
using(var transaction = connection.BeginTransaction())
{
// Code
}
does not commit it, but rather rolls back the whole thing. You have to explicitly invoke transaction.Commit().
You need to commit your transaction.
I had (have) this problem on a website of mine written in PHP. If you are trying to insert a string are you sure you have escaped all necessary characters? Using a single quote in something like don't, won't, or aren't needs to be escaped!