How to perform an INSERT INTO SELECT query in ZF2 - zend-framework

What’s the best way to perform an INSERT INTO SELECT query in ZF2?
I need to develop a function in ZF2 that selects a subset of records from one table and inserts those records into another table. If I were programming in SQL, the statement would look like this:
INSERT INTO target (tgt_col1, tgt_col2)
SELECT 'flag' as marker, src_col2 FROM source
WHERE src_col1='mycriteria'
I’ve searched the Doctrine docs and cannot find an INSERT method. I’ve posted a similar question under the Doctrine tag and the lack of response leads me to believe that INSERT INTO SELECT is too complex for Doctrine to handle.
In ZF2 it appears that I “could” useZend\Db\Sql\Sql. However, for that solution, SELECT and INSERT are two separate functions and it looks like the INSERT function only handles a single record at a time. Therefore, a Zend\Db\Sql\Sql solution would require 1) a group of statements to select the data from the source table, 2) perhaps a function to convert that data object to an array, and 3) a foreach function to cycle through the data array and individually add each record to the target table via 4) a group of insert statements. This seems cumbersome compared to the single statement that’s possible in SQL.
Is there a better way?

If its TableGateway then it definitely works with the latest version of ZF2 i.e. 2.3.2
With reference with the Album module -
Created a duplicate table of album and named it album_old.
Emptied the album table.
So now album table is empty and album_old has the values.
To copy the records from album_old to album, did this -
use Zend\Db\Sql\Select;
....
use Zend\Db\Sql\Insert;
$select = new Select('album_old');
$select->columns(array('artist', 'title', 'cover', 'extra'));
$insert = new Insert();
$insert->into('album');
$insert->columns(array('artist', 'title', 'cover', 'extra'));
$insert->values($select);
//OR
$insert->select($select);
$this->tableGateway->insertWith($insert);
All the values from album_old were inserted into album table.
Ref: https://github.com/zendframework/zf2/blob/master/library/Zend/Db/Sql/Insert.php
Here you will find that the function values() can take array or instanceof Select
and there is a new select() function too.

Related

Sails 1.0 Group By

Now that groupBy is deprecated, how can I mimic a SQL command like SELECT COUNT(*) FROM table GROUP BY xxx using the Waterline ORM ?
This page recommends using .sum() and .avg() but these methods are for number-type columns. Here I want to be able to count the rows of grouped columns, whatever type it is.
I think for specific groupBy query, you've got two choices.
The first one is a 2 step action.
1) Select all the unique element "group by field" you've got in the database.
2) Then count the record for each unique group by field element.
The second one is to use .sendNativeQuery() wich allow you to send a native SQL query to the datastore (you can use this only if you use a real SQL server and not the embedded Sails.JS database)
sendNativeQuery() Documentation

loading dataset where the dataadapter select command uses the IN clause with a subquery

I'm loading a subset of the parent records and the child records into a dataset then setting datarelations and foreignkeyconstraints, so when I am building the dataadapter select stmt for the child records, I must make sure that only the child records whose parent is present is loaded to avoid referential integrity errors. Since the subset of the ParentTable has been loaded into a dataset I tried:
daChild = new OleDBDataAdapter(CreateOledbCommand("select * from Childtable where ChildKey in (ds.tables(""ParentTable""))",dconn))
But got an "undefined function 'ds.tables' in expression" error at runtime.
So, I tried to create a one column table to pass to the IN clause, like this:
Dim MyDataView as DataView = New DataView(ds.tables("ParentTable"))
Dim MyTempParentTable as DataTable = MyDataView.ToTable(False, "ParentKey")
daChild = New OleDbDataAdapter(CreateOledbCommand("select * from ChildTable where ChildKey in (MyTempParentTable)", dconn))
I checked in the debugger, and MyTempParentTable is, in fact, a one column table containing the key of the ParentTable. I thought that the IN clause could take a one column datatable as valid input. Apparently not, as I am getting a "No value given for one or more required parameters" error at runtime.
I'm just about out of ideas. All my google searching came up with for the IN clause was something like IN (value1, value2, value3...) and doesn't give any examples for the IN clause containing a more complex expression.
Can anyone clue me in on what I'm missing, or maybe a different way to accomplish this? I'm trying to get the IN clause to work because I'm thinking that it is the most efficient way to do this... Maybe it's not... Thanks for any help.
I haven't found an answer to the question about why the IN clause didn't work, but just in case anybody else has this issue I will post my workaround.
I load the parent records as usual, but my dataadapter select stmt for the child records has a "WHERE 1=0" so that zero records are initially loaded. When a new parent record is displayed I then determine if the child records for that parent are already loaded into the dataset, if not, I load them in. Bottom line is that I don't pre-load the child records, rather, I load them "on demand". This solution is working well for me.

What is the proper way to insert data to multiple separate tables when inserting into a table?

For example I have a table called product_list, which holds a list of products.
If I insert 1 row of data into product_list, part of the data (such as product_id & product name) should also be inserted in another table like product_price which holds the price for all products (new products would have 0 or NULL values for their price).
My question here is the method in approaching this. What is the proper way to do this?
My current ideas:
1 - Using a trigger to insert into the other tables like product_price,etc whenever I insert a product data into product_list
2 - Using a function (stored procedure) like product_add to add a new product into each tables.
Which method is better? Or if there a better suggestion, then I'd like to know about it. Thanks in advance.

How do I ignore the created column on a Zend_DB table save?

how would I ignore having Zend_DB save() from trying to fill out a created column? I do not need that column for a certain model.
Don't send the data. save() is part of the Zend_Db_Table_Row api and is designed to be somewhat intelligent in the way it saves data to a row. It will perform an insert or an update of a row depending on what is required.
save() will also only update the columns that it has data for. If you don't send new data for your created column save() won't overwrite the data.
When ever it is possible I let the database I'm using create and update the columns for created and updated. That way I have the information available to query if I need it but I don't have to do something with PHP that My database can do better.
Check out http://framework.zend.com/manual/1.12/en/zend.db.table.html Section "Advanced usage".
For more specific and optimized requests, you may wish to limit the
number of columns returned in a row or rowset. This can be achieved by
passing a FROM clause to the select object. The first argument in the
FROM clause is identical to that of a Zend_Db_Select object with the
addition of being able to pass an instance of Zend_Db_Table_Abstract
and have it automatically determine the table name.
Important
The rowset contains rows that are still 'valid' - they simply contain
a subset of the columns of a table. If a save() method is called on a
partial row then only the fields available will be modified.
So, if you called an update() I think it would be as simple as unsetting the value for the column you don't want to touch. Of course database constraints will need to be honored - i.e. column should allow nulls.

iPhone Dev - Trying to access every row of a sqlite3 table sequentially

this is my first time using SQL at all, so this might sound basic. I'm making an iPhone app that creates and uses a sqlite3 database (I'm using the libsqlite3.dylib database as well as importing "sqlite3.h"). I've been able to correctly created the database and a table in it, but now I need to know the best way to get stuff back from it.
How would I go about retrieving all the information in the table? It's very important that I be able to access each row in the order that it is in the table. What I want to do (if this helps) is get all the info from the various fields in a single row, put all that into one object, and then store the object in an array, and then do the same for the next row, and the next, etc. At the end, I should have an array with the same number of elements as I have rows in my sql table. Thank you.
My SQL is rusty, but I think you can use SELECT * FROM myTable and then iterate through the results. You can also use a LIMIT/OFFSET(1) structure if you do not want to retrieve all elements at one from your table (for example due to memory concerns).
(1) Note that this can perform unexpectedly bad, depending on your use case. Look here for more info...
How would I go about retrieving all the information in the table? It's
very important that I be able to access each row in the order that it
is in the table.
That is not how SQL works. Rows are not kept in the table in a specific order as far as SQL is concerned. The order of rows returned by a query is determined by the ORDER BY clause in the query, e.g. ORDER BY DateCreated, or ORDER BY Price.
But SQLite has a rowid virtual column that can be used for this purpose. It reflects the sequence in which the rows were inserted. Except that it might change with a VACUUM. If you make it an INTEGER PRIMARY KEY it should stay constant.
order by rowid