I'm trying to update rows in MySQL from SQL view created with aliases. I do not know if this even is possible.
The original SQL looks like below. This I have saved as a view "ProductVersion".
SELECT e.entity_id AS id,
v1.value AS name,
e.sku,
d1.value AS version
FROM mguu_catalog_product_entity e
LEFT JOIN mguu_catalog_product_entity_varchar v1 ON e.entity_id = v1.entity_id
AND v1.store_id = 0
AND v1.attribute_id =
(SELECT attribute_id
FROM mguu_eav_attribute
WHERE attribute_code = 'name'
AND entity_type_id =
(SELECT entity_type_id
FROM mguu_eav_entity_type
WHERE entity_type_code = 'catalog_product'))
LEFT JOIN mguu_catalog_product_entity_varchar d1 ON e.entity_id = d1.entity_id
AND d1.attribute_id = 171;
Now I would like to perform a MySQL UPDATE from that view, so I tried:
mysqli_query($db, "UPDATE ProductVersion SET version = '123123123' WHERE sku = '1003'");
This does not return any error - however it does not update though. I have also tried like this, but this creates an error:
mysqli_query($db, "UPDATE ProductVersion SET d1.value = '123123123' WHERE e.sku = '1003'");
Is it possible to do an MySQL UPDATE from a view and if not, how would it be done the easiest from the original SQL?
Thanks in advance.
I don't know if that solve the problem but I think you can simplify your View something like this (less useless select statement) :
SELECT e.entity_id AS id,
v1.value AS name,
e.sku as sku,
d1.value AS version
FROM mguu_catalog_product_entity e
LEFT JOIN mguu_catalog_product_entity_varchar v1 ON (e.entity_id = v1.entity_id)
LEFT JOIN mguu_catalog_product_entity_varchar d1 ON (e.entity_id = d1.entity_id)
LEFT JOIN mguu_eav_attribute AS mea ON (v1.attribute_id = mea.attribute_id)
LEFT JOIN mguu_eav_entity_type AS meet ON (meet.entity_type_code = 'catalog_product')
WHERE v1.store_id = 0
AND mea.attribute_code = 'name'
AND mea.entity_type_id = meet.entity_type_id
AND d1.attribute_id = 171;
In MySql documentation :
UPDATE: The table or tables to be updated in an UPDATE statement may be view references that are merged. If a view is a join view, at least one component of the view must be updatable (this differs from INSERT).
In a multiple-table UPDATE statement, the updated table references of the statement must be base tables or updatable view references. Nonupdated table references may be materialized views or derived tables.
https://dev.mysql.com/doc/refman/8.0/en/view-updatability.html
Related
I was able to join 3 tables and count the data set, bet getting the columns on specific table it only see the 3rd table column..
SELECT *
FROM `InvoiceItemTable` a
JOIN `InvoiceTable` b
ON (b.id = a.invoice)
JOIN `products` c
ON (a.product = c.id)
WHERE b.status='1' AND c.store = '2'
//$invoices = $inginger->fetch(PDO::FETCH_ASSOC))
echo $invoices['a.price'];
This price return error : Undefined index: a.price in...
there is "price" in the first table(InvoiceItemTable).
echo $invoices['invoice'];
There is invoice in first table(InvoiceItemTable) and it returns it works
I dont want to use $invoices['price'] because there is 'price' colum in the third table too and that is what it returns, I want to get the price in the first table. $invoices['price.InvoiceItemTable'] returns undefined index
php wont recognize $invoices['a.price']; you have to use $invoices['price'];
if you have same fieldname in multiple tables you have to create an alias
SELECT a.price as a_price, b.price as b_price, c.price as c_price
and then you can use $invoices['a_price']
In general, it's much better to explicitly define your columns. In doing so you can add a specific name to the the column you're interested in (or conversely change the name of the one you're not to remove ambiguity)
For examples sake, I'm just showing the columns you've described but it would look something like.
SELECT a.price as price, c.price as product_price
FROM `InvoiceItemTable` a
JOIN `InvoiceTable` b ON (b.id = a.invoice)
JOIN `products` c ON (a.product = c.id)
WHERE b.status='1' AND c.store = '2';
Doing naming such as this is more work, but insulates your code from changes and more explicitly shows the reader what is being returned.
I need to create the following query (this is just an example) using Zend Framework 1.12 as part of a larger query:
SELECT `s`.*
FROM `s`
INNER JOIN SELECT id FROM table where id = 13 AS `t`
Here's my attempt:
$query = $this->getDbTable()->select()
->from($this->getDbTable(), array('*'))
->join(array('t' => new Zend_Db_Expr('(SELECT id FROM tables where id = 13)')), array())
->setIntegrityCheck(false);
However, this is the output:
SELECT `students`.*, `t`.*
FROM `students`
INNER JOIN SELECT id FROM tables where id = 13 AS `t`
I do not require the t.* from the select since the t table will be used in other ways within the complex query.
Do you know how not to select the t.* but still have the inner join using the subquery?
The Zend_Db_Select->join command is build of two/three parameters.
table name (with possible alias)
on part (ON table1.a = table2.a..)
and the columns you want to select (if you define no parameter here, you end up selecting all the possible fields "t`.*")
In your query you are missing the last parameter. If you assign another parameter to the join (see example below) you should get only the results from the table in your ->from(... part.
->join(array('t' => new Zend_Db_Expr('(SELECT id FROM tables where id = 13)')), array(), array())
I keep falling back into questions with MySQL joining.
And I would like to request a very simple example I could use to continue my journey of understanding learning the MySQL syntax.
Let's say I got the following table's
test_testtable
testtable_id
testtable_name
testtable_user
testtable_option
testtable_textfield
test_testlink
testlink_id
testlink_link
testlink_address
test_address
address_id
address_name
address_phone
address_email
address_street
address_city
address_zip
I would like to make a selection like :
SELECT * (lets say I would define the fields) FROM `test_testable`
JOIN `test_testtable`.`testtable_id` = `test_testlink`.`testlink_link`
AND
JOIN `test_testlink`.`testlink_addres` = `test_address`.`address_id`
WHERE `user_id` = 5
Hence the linking structure is like:
test_testtable.testtable_id = leading
table test_testlink is a table to link the table test_testtable and test_address
And linking table test_testlink uses the field testlink_link to link to the table test_testtable, and uses the field testlink_address to link to the table test_address
This does not work. FOR ME.. Since I continuously seem to fail of catching the correct syntax logic.
So I hope that someone could give me a small example of how to correctly implement such a simple yet critical query!
TIAD!!
A general approach :
SELECT table1.* FROM table1
JOIN table2 ON table2.id_table1 = table1.id
JOIN table3 ON table3.id_table2 = table2.id
WHERE table1.id = 10
For your purpose :
SELECT * (lets say I would define the fields) FROM `test_testable`
JOIN `test_testlink` ON `test_testtable`.`testtable_id` = `test_testlink`.`testlink_link`
JOIN `test_address` ON `test_testlink`.`testlink_addres` = `test_address`.`address_id`
WHERE `user_id` = 5
Please read the reference
You are using wrong syntax. You should mention which tables to join first then based on which fields.
SELECT * (lets say I would define the fields) FROM `test_testable`
INNER JOIN test_testlink
ON `test_testtable`.`testtable_id` = `test_testlink`.`testlink_link`
INNER JOIN `test_address`
ON `test_testlink`.`testlink_addres` = `test_address`.`address_id`
AND `test_testtable`.`user_id` = 5
select * from testlink JOIN testtable ON testlink.tableid = testtable.ID
JOIN testaddress ON testlink.addressid = testaddress.ID
WHERE testtable.ID = 5
I have three tables.
I combine the company and component tables with this code
$questions_query = "SELECT company_mast.id, component_mast.component_id
FROM company_mast
LEFT JOIN component_mast
ON company_mast.id = component_mast.company_id
WHERE component_mast.component_name = '".$component_name."'
AND company_mast.company_name = '".$company_name."'";
The result is as desired, If I put company_name as Bells and component_name as Assets I get and id of 3 for Bells and an id of 9 for Assets. Now if you look at the customfields table I need to pull all the questions with the a specific company_id and component_id.
Example: If the user enters Bells and Assets they need to receive all questions with the company_id of 3 and the component_id of 9.
So this is my query
SELECT *
FROM customfield_mast
LEFT JOIN ( SELECT company_mast.id, component_mast.component_id
FROM company_mast
LEFT JOIN component_mast
ON company_mast.id = component_mast.company_id
WHERE component_mast.component_name = 'Assets'
AND company_mast.company_name = 'Bells')
att
ON customfield_mast.company_id = customfield_mast.component_id
This however returns all questions in my db, which is not what I want. I'm positive my last "ON" statement is the problem, however I don't know what the correct statement would be. I have not started with SQL injection protection, this is grass roots to get my queries to work. Thanks for the help
What's wrong with another join?
SELECT company_mast.id, component_mast.component_id, CFM.DisplayName
FROM company_mast
LEFT JOIN component_mast
ON company_mast.id = component_mast.company_id
LEFT JOIN CustomField_mast CFM
ON CFM.Company_ID = Component_mast.Company_ID
and CFM.Component_ID = component_Mast.Component_ID
WHERE component_mast.component_name = '".$component_name."'
AND company_mast.company_name = '".$company_name."'";
SELECT * FROM `customfield_mast`
WHERE `company_id` =
(SELECT `id` FROM `company_mast` WHERE `company_name` = '$company_name')
AND `component_id` IN
(SELECT GROUP_CONCAT(`component_id`) FROM `component_mast`
WHERE `component_name` = '$component_name')
I've been working on a project that until now has only needed to find 1 row from the joined table. But now I need to grab multiple rows..
So as it stand my sql works something like:
Select rows for each company for this particular project which alone would find company details (name, id, telephone.. blah).
Then I join a table that contains form data submitted for each company (multiple forms - so multiple records)
Until now i have been specifying one formid to look for in the join, but now i need to specify multiple ones.
If I use WHERE form_id = 1 OR form_id = 2 OR form_id = 3 ... I get a result of only the first form match that is found per company..
If I mix up the query so it looks for the forms 1st and returns multiple records for each company with different form data - that works in this sense..
But I am then looping through this array in a view and creating a table row per record (previously each row was a new company) but using the latter would cause multiple records to show for the same company.
Any way I can do this? I tried group by with the latter method but this results in only 1 record again.
SELECT DISTINCT p.project_company_has_user_id, p.project_company_has_user_project_id, p.project_company_has_user_user_id, c.company_id, c.company_hall_no, c.company_company_name, c.company_type, c.company_country, c.company_stand_number, c.company_image_file_1, p2.project_id, p2.project_name, u.user_id, u.user_username, o.orders_id, o2.order_detail_id, o2.order_detail_product_id, f2.form_question_has_answer_id, f2.form_question_has_answer_request, f2.form_question_has_answer_form_id, f2.form_question_has_answer_user_id
FROM project_company_has_user p
INNER JOIN company c ON p.project_company_has_user_company_id = c.company_id
INNER JOIN project p2 ON p.project_company_has_user_project_id = p2.project_id
INNER JOIN user u ON p.project_company_has_user_user_id = u.user_id
INNER JOIN form f ON p.project_company_has_user_project_id = f.form_project_id
LEFT JOIN orders o ON p.project_company_has_user_user_id = o.orders_user_id
LEFT JOIN order_detail o2 ON ((o2.order_detail_orders_id = o.orders_id AND (o2.order_detail_product_id = 65 OR o2.order_detail_product_id = 68 OR o2.order_detail_product_id = 64)))
LEFT JOIN form_question_has_answer f2 ON ((f2.form_question_has_answer_form_id = 297 AND f2.form_question_has_answer_user_id = p.project_company_has_user_user_id))
WHERE (f.form_template_name = "custom" AND p.project_company_has_user_garbage_collection = 0 AND p.project_company_has_user_project_id = 48) AND (LCASE(c.company_country) LIKE "%uk%" OR LCASE(c.company_country) LIKE "%uk%") ORDER BY company_company_name asc
you need another field in order_detail as o2 . this field is row_index(position),etc for positioning record
LEFT JOIN order_detail o2 ON (o2.row_index=1 AND (o2.order_detail_orders_id = o.orders_id AND (o2.order_detail_product_id = 65 OR o2.order_detail_product_id = 68 OR o2.order_detail_product_id = 64)))
Personally I would use an Outer Join for the table of which elements you need to list all matches. Should you them need to clean up that data you can build the logic into the Join Condition (as step 2). Depending on the volume of data you are handling and whether or not you need to reuse it later in the same proc, you may want to post that primary dataset into a temp table and use that as source (primary) for your later logic.
Hope that helps. If you need the code, let me know, but it is pretty straight forward.
Regards
Mac