Stored Procedures - Updating and Inserting - sql

I'm new to using stored procedures, what is the best way to update and insert using stored procedures. I have two tables and I can match them by a distinct ID, I want to update if the ID exists in both my load table and my destination table, and I want to insert if the item does not exist in my destination table. Just an example template would be very helpful, thanks!

If I understood well, you want to select values in one table and insert them in other table. If the id exists in the second table, you need to update the row. If I'm not wrong you need something like this:
mysql> select * from table_1;
+----+-----------+-----------+
| id | name | last_name |
+----+-----------+-----------+
| 1 | fagace | acero |
| 2 | ratangelo | saleh |
| 3 | hectorino | josefino |
+----+-----------+-----------+
3 rows in set (0.00 sec)
mysql> select * from table_2;
+----+-----------+-----------+
| id | name | last_name |
+----+-----------+-----------+
| 1 | fagace | acero |
| 2 | ratangelo | saleh |
+----+-----------+-----------+
2 rows in set (0.00 sec)
mysql> insert into table_2 select t1.id,t1.name,t1.last_name from table_1 t1 on duplicate key update name=t1.name, last_name=t1.last_name;
Query OK, 1 row affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from table_2;
+----+-----------+-----------+
| id | name | last_name |
+----+-----------+-----------+
| 1 | fagace | acero |
| 2 | ratangelo | saleh |
| 3 | hectorino | josefino |
+----+-----------+-----------+
3 rows in set (0.00 sec)
mysql>

You should look up the SQL MERGE statement.
It allows you to perform UPSERT's - i.e. INSERT if a key value does not already exist, UPDATE if the key does exist.
http://technet.microsoft.com/en-us/library/bb510625.aspx
However, your requirement to check for a key value in 2 places before you perform an update does make it more complex. I haven't tried this but I would think a VIEW or a CTE could be used to establish if the ID exists in both your tables & then base the MERGE on the CTE/VIEW.
But definitely start by looking at MERGE!

Related

Why is this Query not Updateable?

I was looking to provide an answer to this question in which the OP has two tables:
Table1
+--------+--------+
| testID | Status |
+--------+--------+
| 1 | |
| 2 | |
| 3 | |
+--------+--------+
Table2
+----+--------+--------+--------+
| ID | testID | stepID | status |
+----+--------+--------+--------+
| 1 | 1 | 1 | pass |
| 2 | 1 | 2 | fail |
| 3 | 1 | 3 | pass |
| 4 | 2 | 1 | pass |
| 5 | 2 | 2 | pass |
| 6 | 3 | 1 | fail |
+----+--------+--------+--------+
Here, the OP is looking to update the status field for each testID in Table1 with pass if the status of all stepID records associated with the testID in Table2 have a status of pass, else Table1 should be updated with fail for that testID.
In this example, the result should be:
+--------+--------+
| testID | Status |
+--------+--------+
| 1 | fail |
| 2 | pass |
| 3 | fail |
+--------+--------+
I wrote the following SQL code in an effort to accomplish this:
update Table1 a inner join
(
select
b.testID,
iif(min(b.status)=max(b.status) and min(b.status)='pass','pass','fail') as v
from Table2 b
group by b.testID
) c on a.testID = c.testID
set a.testStatus = c.v
However, MS Access reports the all-too-familiar, 'operation must use an updateable query' response.
I know that a query is not updateable if there is a one-to-many relationship between the record being updated and the set of values, but in this case, the aggregated subquery would yield a one-to-one relationship between the two testID fields.
Which left me asking, why is this query not updateable?
You're joining in a query with an aggregate (Max).
Aggregates are not updateable. In Access, in an update query, every part of the query has to be updateable (with the exception of simple expressions, and subqueries in WHERE part of your query), which means your query is not updateable.
You can work around this by using domain aggregates (DMin and DMax) instead of real ones, but this query will take a large performance hit if you do.
You can also work around it by rewriting your aggregates to take place in an EXISTS or NOT EXISTS clause, since that's part of the WHERE clause thus doesn't need to be updateable. That would likely minimally affect performance, but means you have to split this query in two: 1 query to set all the fields to "pass" that meet your condition, another to set them to "fail" if they don't.

How to update multiple a rows in mysql

I have a database table like :
+---+-------------+
|id |ship_method |
+---+-------------+
| 1 |freeshipping |
| 1 | flatrate |
| 2 | DHL |
| 3 | matrixrate |
| 1 | courier |
+---+-------------+
So, I want to update ship_method from frontend form based on multi option selected.
For eg : if Id 1 selects freeshipping , DHL , matrixrate then the corresponding values of ship_method should be updated.
What is the mysql query to update in this case. I tried but couldn't find how to update such multiple rows at once.
Delete previous data and insert new all
delete from table where id=1;
insert into table_name(id,ship_method) values(1,'freeshipping'),(1,'DHL'),(1,'matrixrate');

MS Access ComboBox source Query values issue

here is my issue:
I have a combobox, it's source must be union of two tables.
one table is local AllUsers and it has only one record:
+------------+----------+
|IndexKey | UserName |
+----------- +----------+
| -1 | ALL |
+-----------------------+
and the second one is linked from MS SQL Serverdbo_NGAC_USERINFO, I get only Two fields from it:
+-----------+----------+
|IndexKey | Name |
+-----------+----------+
| 1 | Tedo |
+-----------+----------+
| 2 | Tornike |
+-----------+----------+
| 4 | John |
+----------------------+
so, I want to get union result of these tables, it will look like this:
+-----------+----------+
|-1 | ALL |
+-----------+----------+
| 1 | Tedo |
+-----------+----------+
| 2 | Tornike |
+-----------+----------+
| 4 | John |
+----------------------+
But my problem is:
If I write union Query, it shows blank values for IndexKey and correct values Name. but if I write select for only first or only second table in the query, it shows correct results.
here is my code that shows incorrect results:
SELECT *
FROM AllUsers
UNION ALL
SELECT dbo_NGAC_USERINFO.IndexKey, dbo_NGAC_USERINFO.Name
FROM dbo_NGAC_USERINFO
I tried: writing the values from AllUsers Table manually, writing with Union instead of Union All, moving first table in the end and second at the first, ordering, creating subquery, making aliases for fieldnames, but all my tries are unsuccessful.
Any help will be appreciated, thanks in advance.
Try to be more specific:
SELECT AllUsers.IndexKey, AllUsers.Name
FROM AllUsers
UNION ALL
SELECT dbo_NGAC_USERINFO.IndexKey, dbo_NGAC_USERINFO.Name
FROM dbo_NGAC_USERINFO

difference between select * and select table name

This is the basic question about sql statements.
What is the difference between
SELECT * FROM "Users"
and
SELECT "Users".* FROM "Users"
[TableName].[column] is usually used to pinpoint the table you wish to use when two tables a present in a join or a complex statement and you want to define which column to use out of the two with the same name.
It's most common use is in a join though, for a basic statement such as the one above there is no difference and the output will be the same.
In your case there is no difference. It emerges, when you are selecting from multiple tables. * takes data from all the tables, TABLE_NAME.* - all the data from this table. Suppose, we have a database with 2 tables:
mysql> SELECT * FROM report;
+----+------------+
| id | date |
+----+------------+
| 1 | 2013-05-01 |
| 2 | 2013-06-02 |
+----+------------+
mysql> SELECT * FROM sites_to_report;
+---------+-----------+---------------------+------+
| site_id | report_id | last_run | rows |
+---------+-----------+---------------------+------+
| 1 | 1 | 2013-05-01 16:20:21 | 1 |
| 1 | 2 | 2013-05-03 16:20:21 | 1 |
| 2 | 2 | 2013-05-03 14:21:47 | 1 |
+---------+-----------+---------------------+------+
mysql> SELECT
-> *
-> FROM
-> report
-> INNER JOIN
-> sites_to_report
-> ON
-> sites_to_report.report_id=report.id;
+----+------------+---------+-----------+---------------------+------+
| id | date | site_id | report_id | last_run | rows |
+----+------------+---------+-----------+---------------------+------+
| 1 | 2013-05-01 | 1 | 1 | 2013-05-01 16:20:21 | 1 |
| 2 | 2013-06-02 | 1 | 2 | 2013-05-03 16:20:21 | 1 |
| 2 | 2013-06-02 | 2 | 2 | 2013-05-03 14:21:47 | 1 |
+----+------------+---------+-----------+---------------------+------+
mysql> SELECT
-> report.*
-> FROM
-> report
-> INNER JOIN
-> sites_to_report
-> ON
-> sites_to_report.report_id=report.id;
+----+------------+
| id | date |
+----+------------+
| 1 | 2013-05-01 |
| 2 | 2013-06-02 |
| 2 | 2013-06-02 |
+----+------------+
In the case of example given by you, there is no difference between them when it comes to semantics.When it comes to performance it might be too little... just parsing two different length strings....
But, it is only true for the example given by you. Where as in queries where multiple tables are involved tableName.* disambiguate the table from which table we want to select all columns.
Example:
If you have two tables TableA and TableB. Let's suppose that they have column with same names that is Name. If you want to specify from which table you want to select Name column. Table-name qualifier helps.
`select TableA.Name, TableB.Name where TableA.age=TableB.age`
That's all I can say.
The particular examples specified would return the same result and have the same performance. There would be no difference in that respect, therefore.
However, in some SQL products, difference in interpreting * and alias.* has effect, in particular, on what else you can add to the query. More specifically, in Oracle, you can mix an alias.* with other expressions being returned as columns, i.e. this
SELECT "Users".*, SomeColumn * 2 AS DoubleValue FROM "Users"
would work. At the same time, * must stand on its own, meaning that the following
SELECT *, SomeColumn * 2 AS DoubleValue FROM "Users"
would be illegal.
For the examples you provided, the only difference is in syntax. What both of the queries share is that they are really bad. Select * is evil no matter how you write it and can get you into all kinds of trouble. Get into the habit of listing the columns you want to have included in your result set.

Raw copy of database leads to `Can't find file:`

To migrate my database faster, I tried copying the raw files (MYD and MYI) files of a database into another machine. All the tables are working fine except two tables that were partitioned. My directory structure looks like this:
table1.frm
table1.MYI
table1.MYD
table2.frm
table2.par
table2#P#p0.MYD
table2#P#p0.MYI
table2#P#p1.MYD
table2#P#p1.MYI
table3.frm
table3.par
table3#P#p0.MYD
table3#P#p0.MYI
table3#P#p1.MYD
table3#P#p1.MYI
The following is producing an error:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| test |
+--------------------+
3 rows in set (0.06 sec)
mysql> use test;
Database changed
mysql> show tables;
+---------------------------+
| Tables_in_test |
+---------------------------+
| table1 |
| table2 |
| table3 |
+---------------------------+
3 rows in set (0.00 sec)
mysql> explain table1;
+-------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| a | int(11) | YES | | NULL | |
+-------+---------+------+-----+---------+----------------+
2 rows in set (0.01 sec)
mysql> explain table2;
ERROR 1017 (HY000): Can't find file: 'table2' (errno: 2)
mysql> explain table3;
ERROR 1017 (HY000): Can't find file: 'table3' (errno: 2)
mysql> check TABLE table2;
+--------------------------+-------+----------+--------------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+--------------------------+-------+----------+--------------------------------------------------+
| test.table2 | check | Error | Can't find file: 'table2' (errno: 2) |
| test.table2 | check | error | Corrupt |
+--------------------------+-------+----------+--------------------------------------------------+
2 rows in set (0.00 sec)
I checked the permissions and everything looks fine. I tried repair but that didn't seem to work either. Is there anything that can be done?
The server you are porting them to might not have partioning enabled.
Try SHOW VARIABLES LIKE '%partition%'; and check the value of the variable have_partioning or have_partition_engine (depending on your version of mysql).
Further information can be found in the documentation.