PDO - can both CREATE and DROP statements be in the same query? - sql

I have SQL code that executes CREATE TABLE and DROP TABLE in the same query. When I run it, it prints bool(false) meaning error. Can it be done in one query?
$dbh = new PDO("sqlite::memory:");
$stmt = $dbh->prepare("create table a ( i int, j int);drop table a");
var_dump($stmt);
I don't know why but it works if I try it again.

You need to execute your query
Like this :
$stmt ->execute();
And yes you can create and delete a table in the same query.
You can maybe try this to catch an error, it will help you
try
{
$db = new PDO('sqlite::memory');
echo "SQLite created in memory.";
}
catch(PDOException $e)
{
echo $e->getMessage();
}

Related

Truncate all tables before running seed files with Phinx

So, I have been creating migrations using Phinx. I want to be able to truncate all the tables(148 tables) before running the seed files. I am thinking about just creating a seed file that will be ran first and then it will truncate all the tables. The catch is that I don't want to have to ever change this file if we add more tables. How would I go about doing this. Maybe doing a Show tables and then looping through them, but not exactly sure how to do that. Any help would be great! This is what I have so far.
<?php
use Phinx\Seed\AbstractSeed;
class BonusRuleTypesSeeder extends AbstractSeed
{
public function run()
{
$this->execute('SET foreign_key_checks=0');
// some code here
$this->execute('SET foreign_key_checks=1');
}
}
If you have a migrations table, then this will truncate that table as well. This would work.
$this->execute('SET foreign_key_checks=0');
foreach($tables as $table){
$table = $table["Tables_in_".$database];
if ($table != $config->getProperty(['phinx', 'default_migration_table'])){
$sql = "TRUNCATE TABLE ".$table;
$this->execute($sql);
}
}
Here is the answer
$config = new Config(__DIR__.'/../../config/default.ini',true);
$host = $config->getProperty(['db', 'host']);
$database = $config->getProperty(['db', 'name']);
$username = $config->getProperty(['db', 'username']);
$password = $config->getProperty(['db', 'password']);
$mysqli = new mysqli($host, $username, $password, $database);
$query = "Show tables";
$tables = $mysqli->query($query);
$tables->fetch_all();
$mysqli->close();
$this->execute('SET foreign_key_checks=0');
foreach($tables as $table){
$table = $table["Tables_in_".$database];
$sql = "TRUNCATE TABLE ".$table;
$this->execute($sql);
}
$this->execute('SET foreign_key_checks=1');

PHP - table not created

I have installed PHP, Apache and MySQL manually on my MacBook and I'm following a book about how to create the table without using phpMyAdmin. My script doesn't seem to be creating the DNS, however, it doesn't throw any exceptions. Any suggestions, guys? Thanks in advance.
This is my code: file name: setup.php
<?php
print("Created.\n"); // This statement prints
$db = new PDO("mysql:host=localhost;dbname=MyBlog", "username", "password");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
print("Created.\n"); // This statement does not print
try {
$queryStr = "CREATE TABLE users (id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(40), password VARCHAR(100), email VARCHAR(150))";
$db->query($queryStr);
print("Created.\n");
} catch (PDOException $e) {
echo $e->getMessage();
}
You should write the code where you instatiate and set up the PDO object in the try block. That way you can catch exceptions that occur during connect etc.

Magento - Module INSERT,UPDATE, DELETE, SELECT code

I created a module and want to used core write and read function to insert,update,delete or select database value with condition, how can I do it without using SQL?
Example:
$customer_id=123
Model=(referral/referral)
SELECT
$collection3 = Mage::getModel('referral/referral')->getCollection();
$collection3->addFieldToFilter('customer_id', array('eq' => $customer_id));
foreach($collection3 as $data1)
{
$ref_cust_id.= $data1->getData('referral_customer_id');
}
INSERT
$collection1= Mage::getModel('referral/referral');
$collection1->setData('customer_id',$customer_id)->save();
DELETE,UPDATE(with condition)=???
Suppose, I have a module named mynews.
Here follows the code to select, insert, update, and delete data from the news table.
INSERT DATA
$data contains array of data to be inserted. The key of the array should be the database table’s field name and the value should be the value to be inserted.
$data = array('title'=>'hello there','content'=>'how are you? i am fine over here.','status'=>1);
$model = Mage::getModel('mynews/mynews')->setData($data);
try {
$insertId = $model->save()->getId();
echo "Data successfully inserted. Insert ID: ".$insertId;
} catch (Exception $e){
echo $e->getMessage();
}
SELECT DATA
$item->getData() prints array of data from ‘news’ table.
$item->getTitle() prints the only the title field.
Similarly, to print content, we need to write $item->getContent().
$model = Mage::getModel('mynews/mynews');
$collection = $model->getCollection();
foreach($collection as $item){
print_r($item->getData());
print_r($item->getTitle());
}
UPDATE DATA
$id is the database table row id to be updated.
$data contains array of data to be updated. The key of the array should be the database table’s field name and the value should be the value to be updated.
// $id = $this->getRequest()->getParam('id');
$id = 2;
$data = array('title'=>'hello test','content'=>'test how are you?','status'=>0);
$model = Mage::getModel('mynews/mynews')->load($id)->addData($data);
try {
$model->setId($id)->save();
echo "Data updated successfully.";
} catch (Exception $e){
echo $e->getMessage();
}
DELETE DATA
$id is the database table row id to be deleted.
// $id = $this->getRequest()->getParam('id');
$id = 3;
$model = Mage::getModel('mynews/mynews');
try {
$model->setId($id)->delete();
echo "Data deleted successfully.";
} catch (Exception $e){
echo $e->getMessage();
}
In this way you can perform select, insert, update and delete in your custom module and in any magento code.
Source: http://blog.chapagain.com.np/magento-how-to-select-insert-update-and-delete-data/
UPDATE is basically the combination of SELECT and INSERT. You load a collection, iterate over them setting the values as needed, then call ->save() on each model.
DELETE is handled directly via the ->delete() functon of models. So either load a single model or iterate over a SELECTed collection of them and call ->delete()
(Not that due to the iteration, this is not the 'fastest' way of doing these operations on collections (because each one is going to generate a new query, instead of a single query that handles multiple deletes at once), but the performance is fine for either small data sets/SELECTs (less than 1k?) or for things that you don't do very often (like importing or updating prices ok 10k products once per day).
FOR UPDATE
$new=$this->getRequest()->getParams();
$id=$new['id'];
$name=$new['name'];
$con=Mage::getModel('plugin/plugin')->load($id);
$con->setData('name',$name)->save();
echo "Update Success";
FOR DELETE
$id = $this->getRequest()->getParam('id');
$model = Mage::getModel('plugin/plugin');
$model->setId($id)->delete();
echo "Data deleted successfully.";
You can use select query like this also. its very easy.
$salesInvoiceCollection_sql = "SELECT `entity_id` , `increment_id`,`order_id`
FROM `sales_flat_invoice`
WHERE `erp_invoice_id` = 0
ORDER BY `entity_id`
DESC limit 1000";
$salesInvoiceCollection = Mage::getSingleton('core/resource')->getConnection('core_read')->fetchAll($salesInvoiceCollection_sql);
If you want to delete with condition based on collection you can use addFieldToFilter, addAttributeToFilter
$model = Mage::getModel('mynews/mynews')->getCollection();
try {
$model->addAttributeToFilter('status', array('eq' => 1));
$model->walk('delete');
echo "Data deleted successfully.";
} catch (Exception $e){
echo $e->getMessage();
}

How can I UPDATE rows returned by a SELECT in a loop?

I have a loop on the rows returned by an SQL SELECT statement, and, after some processing on a row's data, I sometimes want to UPDATE the row's value. The processing in the loop's body is non-trivial, and I can't write it in SQL. When I try to execute the UPDATE for the selected row I get an error (under Perl's DBD::SQLite::st execute failed: database table is locked). Is there a readable, efficient, and portable way to achieve what I'm trying to do? Failing that, is there a DBD or SQLite-specific way to do it?
Obviously, I can push the updates in separate data structure and execute them after the loop, but I'd hate the code's look after that.
If you're interested, here is the corresponding Perl code.
my $q = $dbh->prepare(q{
SELECT id, confLoc FROM Confs WHERE confLocId ISNULL});
$q->execute or die;
my $u = $dbh->prepare(q{
UPDATE Confs SET confLocId = ? WHERE id = ?});
while (my $r = $q->fetchrow_hashref) {
next unless ($r->{confLoc} =~ m/something-hairy/);
next unless ($locId = unique_name_state($1, $2));
$u->execute($locId, $r->{id}) or die;
}
Temporarily enable AutoCommit:
sqlite> .header on
sqlite> select * from test;
field
one
two
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
my $dbh = DBI->connect('dbi:SQLite:test.db', undef, undef,
{ RaiseError => 1, AutoCommit => 0}
);
test_select_with_update($dbh);
sub test_select_with_update {
my ($dbh) = #_;
local $dbh->{AutoCommit} = 1;
my $q = $dbh->prepare(q{SELECT field FROM test});
my $u = $dbh->prepare(q{UPDATE test SET field = ? WHERE field = ?});
$q->execute or die;
while ( my $r = $q->fetchrow_hashref ) {
if ( (my $f = $r->{field}) eq 'one') {
$u->execute('1', $f) or die;
}
}
}
After the code has been run:
sqlite> .header on
sqlite> select * from test;
field
1
two
Your problem is that you're using the same database handler to perform an update while you're in a fetching loop.
So have another instance of your database handler to perform the updates:
my $dbh = DBI->connect(...);
my $dbhForUpdate = DBI->connect(...) ;
Then use dbhForUpdate in your loop:
while(my $row = $sth->fetch()){
...
$dbhForUpdate->do(...) ;
}
Anyway, I wouldn't recommend doing this since there's good chances you run into concurrency issues at the database level.
More in answer to Zoidberg's comment but if your were able to switch to an ORM like Perl's DBIx::Class then you find that you could write something like this:
my $rs = $schema->resultset('Confs')->search({ confLocId => undef });
while ( my $data = $rs->next ) {
next unless $data->confLoc =~ m/(something)-(hairy)/;
if ( my $locId = unique_name_state( $1, $2 ) ) {
$data->update({ confLocID => $locid });
}
}
And if DBIx::Class doesn't grab your fancy there are a few others on CPAN like Fey::ORM and Rose::DB for example.

How can I avoid the program quitting when Perl's DBI encounters an error preparing a statement?

I'm making a script that goes through a table that contains all the other table names on the database. As it parses each row, it checks to see if the table is empty by
select count(*) cnt from $table_name
Some tables don't exist in the schema anymore and if I do that
select count(*)
directly into the command prompt, it returns the error:
206: The specified table (adm_rpt_rec) is not in the database.
When I run it from inside Perl, it appends this to the beginning:
DBD::Informix::db prepare failed: SQL: -
How can I avoid the program quitting when it tries to prepare this SQL statement?
One option is not to use RaiseError => 1 when constructing $dbh. The other is to wrap the prepare in an eval block.
Just put the calls that may fail in an eval block like this:
for my $table (#tables) {
my $count;
eval {
($count) = $dbi->selectrow_array("select count(*) from $table");
1; #this is here so the block returns true if it succeeds
} or do {
warn $#;
next;
}
print "$table has $count rows\n";
}
Although, in this case, since you are using Informix, you have a much better option: the system catalog tables. Informix keeps metadata like this in a set of system catalog tables. In this case you want systables:
my $sth = $dbh->prepare("select nrows from systables where tabname = ?");
for my $table (#tables) {
$sth->execute($table);
my ($count) = $sth->fetchrow_array;
$sth->finish;
unless (defined $count) {
print "$table does not exist\n";
next;
}
print "$table has $count rows\n";
}
This is faster and safer than count(*) against the table. Full documentation of the system catalog tables can be found in IBM Informix Guide to SQL (warning this is a PDF).
Working code - assuming you have a 'stores' database.
#!/bin/perl -w
use strict;
use DBI;
my $dbh = DBI->connect('dbi:Informix:stores','','',
{RaiseError=>0,PrintError=>1}) or die;
$dbh->do("create temp table tlist(tname varchar(128) not null) with no log");
$dbh->do("insert into tlist values('systables')");
$dbh->do("insert into tlist values('syzygy')");
my $sth = $dbh->prepare("select tname from tlist");
$sth->execute;
while (my($tabname) = $sth->fetchrow_array)
{
my $sql = "select count(*) cnt from $tabname";
my $st2 = $dbh->prepare($sql);
if ($st2)
{
$st2->execute;
if (my($num) = $st2->fetchrow_array)
{
print "$tabname: $num\n";
}
else
{
print "$tabname: error - missing?\n";
}
}
}
$sth->finish;
$dbh->disconnect;
print "Done - finished under control.\n";
Output from running the code above.
systables: 72
DBD::Informix::db prepare failed: SQL: -206: The specified table (syzygy) is not in the database.
ISAM: -111: ISAM error: no record found. at xx.pl line 14.
Done - finished under control.
This printed the error (PrintError=>1), but continued. Change the 1 to 0 and no error appears. The parentheses in the declarations of $tabname and $num are crucial - array context vs scalar context.