Built on top of [PDO](http://www.php.net/manual/en/book.pdo.php), Yii DAO (Database Access Objects) provides an
object-oriented API for accessing relational databases. It is the foundation for other more advanced database
access methods, including [query builder](db-query-builder.md) and [active record](db-active-record.md).
Yii includes a database access layer built on top of PHP's [PDO](http://www.php.net/manual/en/book.pdo.php). The database access objects (DAO) interface provides a
uniform API, and solves some inconsistencies that exist between different database applications. Whereas Active Record provides database interactions through models, and the Query Builder assists in composing dynamic queries, DAO is a simple and efficient way to execute straight SQL on your database. You'll want to use DAO when the query to be run is expensive and/or no application models--and their corresponding business logic--are required.
When using Yii DAO, you mainly need to deal with plain SQLs and PHP arrays. As a result, it is the most efficient
way to access databases. However, because SQL syntax may vary for different databases, using Yii DAO also means
you have to take extra effort to create a database-agnostic application.
By default, Yii supports the following DBMS:
Yii DAO supports the following databases out of box:
-[MySQL](http://www.mysql.com/)
-[MariaDB](https://mariadb.com/)
-[SQLite](http://sqlite.org/)
-[PostgreSQL](http://www.postgresql.org/)
-[CUBRID](http://www.cubrid.org/): version 9.3 or higher. (Note that due to a [bug](http://jira.cubrid.org/browse/APIS-658) in
the cubrid PDO extension, quoting of values will not work, so you need CUBRID 9.3 as the client as well as the server)
-[CUBRID](http://www.cubrid.org/): version 9.3 or higher.
Please refer to the [PHP manual](http://www.php.net/manual/en/function.PDO-construct.php) for more details
on the format of the DSN string. Refer to [[yii\db\Connection]] for the full list of properties you can configure in the class.
You can then access the DB connection via the expression `Yii::$app->db`.
> Tip: You can configure multiple DB application components if your application needs to access multiple databases.
When configuring a DB connection, you should always specify its Data Source Name (DSN) via the [[yii\db\Connection::dsn|dsn]]
property. The format of DSN varies for different databases. You may refer to Please refer to the [PHP manual](http://www.php.net/manual/en/function.PDO-construct.php)
If you don't want to define the connection as an [application component](structure-application-components.md), you can instantiate it directly:
Once you have a database connection instance, you can execute a SQL query by taking the following steps:
1. Create a [[yii\db\Command]] with a plain SQL;
2. Bind parameters (optional);
3. Call one of the SQL execution methods in [[yii\db\Command]].
The following examples various ways of fetching data from a database:
```php
$connection=new\yii\db\Connection([
'dsn'=>$dsn,
'username'=>$username,
'password'=>$password,
]);
$connection->open();
$db=newyii\db\Connection(...);
// return a set of rows. each row is an associative array of column names and values.
// an empty array is returned if no results
$posts=$db->createCommand('SELECT * FROM post')
->queryAll();
// return a single row (the first row)
// false is returned if no results
$post=$db->createCommand('SELECT * FROM post WHERE id=1')
->queryOne();
// return a single column (the first column)
// an empty array is returned if no results
$titles=$db->createCommand('SELECT title FROM post')
->queryColumn();
// return a scalar
// false is returned if no results
$count=$db->createCommand('SELECT COUNT(*) FROM post')
->queryScalar();
```
> Tip: If you need to execute an SQL query immediately after establishing a connection (e.g., to set the timezone or character set), you can add the following to your application configuration file:
> Note: To preserve precision, the data fetched from databases are all represented as strings, even if the corresponding
database column types are numerical.
> Tip: If you need to execute a SQL query right after establishing a connection (e.g., to set the timezone or character set),
> you can do so in the [[yii\db\Connection::EVENT_AFTER_OPEN]] event handler. For example,
The `queryXyz()` methods introduced in the previous sections all deal with SELECT queries which fetch data from databases.
For queries that do not bring back data, you should call the [[yii\db\Command::execute()]] method instead. For example,
```php
$command=$connection->createCommand('UPDATE post SET status=1 WHERE id=1');
$command->execute();
$db->createCommand('UPDATE post SET status=1 WHERE id=1')
->execute();
```
Alternatively, you can use the dedicated `insert`, `update`, and `delete` methods. These methods will properly quote table and column names used in your query, and you only need to provide the necessary values:
The [[yii\db\Command::execute()]] method returns the number of rows affected by the SQL execution.
[[Ought to put a link to the reference docs here.]]
For INSERT, UPDATE and DELETE queries, instead of writing plain SQLs, you may call [[yii\db\Command::insert()|insert()]],
[[yii\db\Command::update()|update()]], [[yii\db\Command::delete()|delete()]], respectively, to build the corresponding
SQLs. These methods will properly quote table and column names and bind parameter values. For example,
// executes this SQL for MySQL: SELECT COUNT(`id`) FROM `employee`
$count=$db->createCommand("SELECT COUNT([[id]]) FROM {{employee}}")
->queryScalar();
```
In the code above, `[[$column]]` will be converted to a properly quoted column name, while `{{table}}` will be converted to a properly quoted table name.
There's a special variant on this syntax specific to tablenames: `{{%Y}}` automatically appends the application's table prefix to the provided value, if a table prefix has been set:
### Using Table Prefix <a name="using-table-prefix"></a>
// executes this SQL for MySQL: SELECT COUNT(`id`) FROM `tbl_employee`
$count=$db->createCommand("SELECT COUNT([[id]]) FROM {{employee}}")
->queryScalar();
```
Using Prepared Statements
-------------------
To securely pass query parameters to your queries, you should make use of prepared statements. First, create a named placeholder in your query (using the syntax `:placeholder`). Then bind the placeholder to a variable and execute the query:
$command = $connection->createCommand('SELECT * FROM post WHERE id=:id');
$command->bindValue(':id', $_GET['id']);
$post = $command->queryOne();
```
When running multiple related queries in a sequence, you may need to wrap them in a transaction to ensure the integrity
and consistency of your database. If any of the queries fails, the database will be rolled back to the state as if
none of these queries is executed.
Another purpose for prepared statements (aside from improved security) is the ability to execute a query multiple times while preparing it only once:
The following code shows a typical way of using transactions:
```php
$command = $connection->createCommand('DELETE FROM post WHERE id=:id');
$command->bindParam(':id', $id);
$id = 1;
$command->execute();
$id = 2;
$command->execute();
$db->transaction(function($db){
$db->createCommand($sql1)->execute();
$db->createCommand($sql2)->execute();
// ... executing other SQL statements ...
});
```
Notice that you bind the placeholder to the variable before the execution, and then change the value of that variable before each subsequent execution (this is often done with loops). Executing queries in this manner can be vastly more efficient than running each query one at a time.
Performing Transactions
-----------------------
When running multiple, related queries in a sequence, you may need to wrap them in a transaction to
protect your data's integrity. Transactions allow you to write a series of queries such that they'll all succeed or have no effect whatsoever. Yii provides a simple interface to work with transactions in simple
cases but also for advanced usage when you need to define isolation levels.
The following code shows a simple pattern that all code that uses transactional queries should follow:
The above code is equivalent to the following:
```php
$transaction = $connection->beginTransaction();
$transaction=$db->beginTransaction();
try{
$connection->createCommand($sql1)->execute();
$connection->createCommand($sql2)->execute();
$db->createCommand($sql1)->execute();
$db->createCommand($sql2)->execute();
// ... executing other SQL statements ...
$transaction->commit();
}catch(\Exception$e){
$transaction->rollBack();
throw$e;
}
```
The first line starts a new transaction using the [[yii\db\Connection::beginTransaction()|beginTransaction()]] method of the database connection
object. The transaction itself is represented by a [[yii\db\Transaction]] object stored in `$transaction`.
We wrap the execution of all queries in a try-catch block to be able to handle errors.
We call [[yii\db\Transaction::commit()|commit()]] on success to commit the transaction and
[[yii\db\Transaction::rollBack()|rollBack()]] in case of an error. This will revert the effect of all queries
that have been executed inside of the transaction.
`throw $e` is used to re-throw the exception in case we can not handle the error ourselves and delegate it
to some other code or the Yii error handler.
By calling the [[yii\db\Connection::beginTransaction()|beginTransaction()]] method, a new transaction is started.
The transaction is represented as a [[yii\db\Transaction]] object stored in the `$transaction` variable. Then,
the queries being executed are enclosed in a `try...catch...` block. If all queries are executed successfully,
the [[yii\db\Transaction::commit()|commit()]] method is called to commit the transaction. Otherwise, an exception
will be triggered and caught, and the [[yii\db\Transaction::rollBack()|rollBack()]] method is called to roll back
the changes made the queries prior to that failed query in the transaction.
It is also possible to nest multiple transactions, if needed: