Retrieving two columns from one table inserting into another table using mySQL and PHP - sql

I have two tables in mySQL, notably accounts and subscriber_data.
I want to use two columns present in the accounts table (id, name), and insert it to the subscriber_data table in two columns called (sub_id, value).
I cannot seem to find a way to retrieve this information and put it into the other table without it being bunched up in the same value field in the same row like this: 0, 0, 1
Currently, my PHP looks like this:
$sql = "SELECT * FROM accounts";
$result = mysql_query($sql);
while($alt_result = mysql_fetch_array($result, MYSQL_NUM)){
$id[] = $alt_result[0];
$value1[] = $alt_result[1];
}
$idstring = implode(', ', $id);
$value1 = implode(', ', $value1);
$sql = "INSERT INTO subscriber_data (field_id, sub_id, value) VALUES('1', '$idstring', '$value1') ON DUPLICATE KEY UPDATE value='$value1'";
$result = mysql_query($sql);
I am a novice at this, and obviously doing something wrong... I searched and couldn't find an answer.
Thanks.

I didn't see at first what you were doing in PHP before calling the insert script. Maybe because I'm not used to PHP scripting, though more probably because I didn't pay enough attention at the time.
So, as far as I can understand what you are doing, you seem to be doing it wrong way.
If you need to insert values from one table into another table, you just use the INSERT...SELECT construct.
In your case it should possibly be something like this:
INSERT INTO subscriber_data (field_id, sub_id, value)
SELECT '1', id, name
FROM accounts
Note that this is one instruction, and it replaces both SELECT... and INSERT... in your code. I think it will be enough if you leave only the last two lines of your PHP script above, where the SQL script you are storing to $sql should simply be modified according to my suggestion.
If I'm missing something, please let me know.

Related

Dealing with multiple output results in UPSERT query [SQL]

I'm trying to do an update query in which a single row the table is updated and, if nothing has matched and updated, a new row is inserted. In each case, I need the query to return the ID of the inserted row.
The issue I'm having is this query is returning 2 separate results when the insert case is reached, one for each output (the first empty, the second containing the ID). I'm running this query using SQL Alchemy on python and I'm only able to see the first result, which is empty.
UPDATE [Rights]
SET accessLevel = :access_level
OUTPUT inserted.rightsID
WHERE principal = :principal and [function] = :function
IF ##ROWCOUNT = 0
INSERT INTO Rights(principal, [function], accessLevel)
OUTPUT inserted.rightsID
VALUES(:principal, :function, :access_level)
And I'm calling it like so:
inserted_right_id = session.execute(sql_rights_update, right).fetchall()
Can anyone recommend a way of changing the query so that I can still use the UPSERT method, but only receive one of the IDs? I was considering storing the OUTPUT values into a table and returning that, or wrapping the whole thing in a select but hopefully there's something more elegant out there.
Thanks a million.
Feeling quite dumb. I simply added a
IF EXISTS(SELECT * FROM Rights WHERE principal = :principal and [function] = :function)
UPDATE ...
ELSE
INSERT ...

sqlite data from one db to another

I have 2 sqlite databases, and I'm trying to insert data from one database to another. For example, "db-1.sqlite" has a table '1table' with 2 columns ('name', 'state'). Also, "db-2.sqlite" has a table '2table' with 2 columns ('name', 'url'). Both tables contain a list of 'name' values that are mostly common with each other but randomized, so the id of each row does not match.
I want to insert the values for the 'url' column into the db-1's table, but I want to make sure each url value goes to its corresponding 'name' value.
So far, I have done this:
> sqlite3 db-1.sqlite
sqlite> alter table 1table add column url;
sqlite> attach database 'db-2.sqlite' as db2;
Now, the part I'm not sure about:
sqlite> insert into 1table(url) select db2.2table.url from db2.2table where 1table.name==db2.2table.name
If you look at what I wrote above, you can tell what I'm trying to accomplish, but it is incorrect. If I can get any help on the matter, I'd be very grateful!!
The equality comparison operator in SQL is =, not ==.
Also, I suspect that you should be updating 1table, rather then inserting in it.
Finally, your table names start with digits, so you need to escape them.
This SQL should work better:
update `1table`
set url = (select db2.`2table`.url
from db2.`2table`
where `1table`.name = db2.`2table`.name);

SQL LIKE query not working

I'm trying to run the following query against an Oracle DB, but the query is returning 0 records:
select * from TABLE
where upper(FIELD) like '%SEE COMMENT%'
I know this field contains many records with 'See Comment" in it. For example, here is one of the records:
=if(and(Robust_Mean>=20,Robust_Mean<=70),.03*(Robust_Mean+29),
if(Robust_Mean>70,.083*(Robust_Mean^.9),"See Comment"))
I am guessing that the quotation marks in the field are messing the query up, but im not sure how to get around it. Any suggestions?
This works for me:
create table testLike (aCol varchar2(500) );
INSERT INTO TESTLIKE VALUES('abc');
insert into testLike values('=if(and(Robust_Mean>=20,Robust_Mean<=70),.03*(Robust_Mean+29),
if(Robust_Mean>70,.083*(Robust_Mean^.9),"See Comment"))');
SELECT *
FROM TESTLIKE TL
WHERE upper(tl.acol) like '%SEE COMMENT%';
can you recreate?
edit:
in your query try this:
select * from TABLE
WHERE UPPER(FIELD) = '=if(and(Robust_Mean>=20,Robust_Mean<=70),.03*(Robust_Mean+29),
if(Robust_Mean>70,.083*(Robust_Mean^.9),"See Comment"))';
see if that comes up with any results
Just realized there were two similarly named fields in this table, and I was choosing the wrong one.

Select the last row in a SQL table

Is it possible to return the last row of a table in MS SQL Server.
I am using an auto increment field for the ID and i want to get the last one just added to join it with something else. Any idea?
Here's the code:
const string QUERY = #"INSERT INTO Questions (ID, Question, Answer, CategoryID, Permission) "
+ #"VALUES (#ID, #Question, #Answer, #CategoryID, #Permission) ";
using (var cmd = new SqlCommand(QUERY, conn))
{
cmd.Parameters.AddWithValue("#Question", question);
cmd.Parameters.AddWithValue("#Answer", answer);
cmd.Parameters.AddWithValue("#CategoryID", lastEdited);
cmd.Parameters.AddWithValue("#Permission", categoryID);
cmd.ExecuteNonQuery();
}
Not safe - could have multiple inserts going on at the same time and the last row you'd get might not be yours. You're better off using SCOPE_IDENTITY() to get the last key assigned for your transaction.
using an auto increment field ... and i want to get the last one just added to join it with something else.
The key here is "just added". If you have a bunch of different users hit the db at the same time, I don't think you want user A to retrieve the record created by user B. That means you probably want to use the scope_identity() function to get that id rather than running a query on the table again right away.
Depending on the context you might also need ##identity (would include triggers) or ident_current('questions') (limited to a specific table, but not the specific scope). But scope_identity() is almost always the right one to use.
Here's an example:
DECLARE #NewOrderID int
INSERT INTO TABLE [Orders] (CustomerID) VALUES (1234)
SELECT #NewOrderID=scope_identity()
INSERT INTO TABLE [OrderLines] (OrderID, ProductID, Quantity)
SELECT #NewOrderID, ProductID, Quantity
FROM [ShoppingCart]
WHERE CustomerID=1234 AND SessionKey=4321
Based on the code you posted, you can do something like this:
// don't list the ID column: it should be an identity column that sql server will handle for you
const string QUERY = "INSERT INTO Questions (Question, Answer, CategoryID, Permission) "
+ "VALUES (#Question, #Answer, #CategoryID, #Permission);"
+ "SELECT scope_identity();";
int NewQuestionID;
using (var cmd = new SqlCommand(QUERY, conn))
{
cmd.Parameters.AddWithValue("#Question", question);
cmd.Parameters.AddWithValue("#Answer", answer);
cmd.Parameters.AddWithValue("#CategoryID", lastEdited);
cmd.Parameters.AddWithValue("#Permission", categoryID);
NewQuestionID = (int)cmd.ExecuteScalar();
}
See my answer to another question here:
get new SQL record ID
The problem now is that you'll likely want subsequent sql statements to be in the same transaction. You could do this with client code, but I find keeping it all on the server to be cleaner. You could do that by building a very long sql string, but I tend to prefer a stored procedure at this point.
I'm also not a fan of the .AddWithValue() method — I prefer explicitly defining the parameter types — but we can leave that for another day.
Finally, it's kind of late now, but I want to emphasize that it's really better to try to keep this all on the db. It's okay to run multiple statements in one sql command, and you want to reduce the number of round trips you need to make to the db and the amount of data you need to pass back and forth between the db and your app. It also makes it easier to get the transactions right and keep things atomic where they need to be.
use
scope_identity() returns the last identity value generated in this session and this scope
ident_current() returns the last identity value generated for a particular table in any session and any scope
select ident_current( 'yourTableName' )
will return the last identity created by a different session.
Most of the time you should use scope_identity() right after an insert statement like so.
--insert statement
SET #id = CAST(SCOPE_IDENTITY() AS INT)
MSDN Link - Scope_Identity()
MSDN Link - Ident_Current
select top 1 * from yourtable order by id desc
I'm not sure of your version of SQL Server, but look for the OUTPUT clause of ther INSERT statement. You can capture a set of rows with this clause
Since the questioner is using .NET, here's a modified example of how to do it. (I removed ID from the insert list since it's autoincrement--the original example would fail. I also assume ID is an SQL int, not a bigint.)
const string QUERY = #"INSERT INTO Questions (Question, Answer, CategoryID, Permission) "
+ #"VALUES (#Question, #Answer, #CategoryID, #Permission);"
+ #"SELECT #ID = SCOPE_IDENTITY();";
using (var cmd = new SqlCommand(QUERY, conn))
{
cmd.Parameters.AddWithValue("#Question", question);
cmd.Parameters.AddWithValue("#Answer", answer);
cmd.Parameters.AddWithValue("#CategoryID", lastEdited);
cmd.Parameters.AddWithValue("#Permission", categoryID);
cmd.Parameters.Add("#ID", System.Data.SqlDbType.Int).Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
int id = (int)cmd.Parameters["#ID"].Value;
}
EDITED: I also suggest considering LINQ to SQL instead of hand-coding SqlCommand objects--it's much better (faster to code, easier to use) for many common scenarios.
With a simple select you can do something like this:
SELECT *
FROM table_name
WHERE IDColumn=(SELECT max(IDColum) FROM table_name)

SQL: Use the same string for both INSERT and UPDATE?

The INSERT syntax I've been using is this
INSERT INTO TableName VALUES (...)
The UPDATE syntax I've been using is
UPDATE TableName SET ColumnName=Value WHERE ...
So in all my code, I have to generate 2 strings, which would result in something like this
insertStr = "(27, 'John Brown', 102)";
updateStr = "ID=27, Name='John Brown', ItemID=102";
and then use them separately
"UPDATE TableName SET " + updateStr + " WHERE ID=27 " +
"IF ##ROWCOUNT=0 "+
"INSERT INTO TableName VALUES (" + insertStr + ")"
It starts bothering me when I am working with tables with like 30 columns.
Can't we generate just one string to use on both INSERT and UPDATE?
eg. using insertStr above on UPDATE statement or updateStr on INSERT statement, or a whole new way?
I think you need a whole new approach. You are open to SQL Injection. Provide us with some sample code as to how you are getting your data inputs and sending the statements to the database.
alt text http://goose.ycp.edu/~weddins/440/S09%20IFS440%20Bobby%20Drop%20Tables.PNG
As far as I'm aware, what you're describing isn't possible in ANSI SQL, or any extension of it that I know. However, I'm mostly familiar with MySQL, and it likely depends completely upon what RDBMS you're using. For example, MySQL has "INSERT ... ON DUPLICATE KEY UPDATE ... " syntax, which is similar to what you've posted there, and combines an INSERT query with an UPDATE query. The upside is that you are combining two possible operations into a single query, however, the INSERT and UPDATE portions of the query are admittedly different.
Generally, this kind of thing can be abstracted away with an ORM layer in your application. As far as raw SQL goes, I'd be interested in any syntax that worked the way you describe.
Some DBMS' have an extension to do this but why don't you just provide a function to do it for you? We've actually done this before.
I'm not sure what language you're using but it's probably got associative arrays where you can wrote something like:
pk{"ID"} = "27"
val{"Name"} = "'John Brown'"
val{"ItemID"} = "102"
upsert ("MyTable", pk, val)
and, if it doesn't have associative arrays, you can emulate them with multiple integer-based arrays of strings.
In our upsert() function, we just constructed a string (update, then insert if the update failed) and passed it to our DBMS. We kept the primary keys separate from our other fields since that made construction of the update statement a lot easier (primary key columns went in the where clause, other columns were just set).
The result of the calls above would result in the following SQL (we had a different check for failed update but I've put your ##rowcount in for this example):
update MyTable set
Name = 'John Brown',
ItemID = 102
where ID = 27
if ##rowcount=0
insert into MyTable (ID, Name, ItemID) values (
27,
'John Brown',
102
)
That's one solution which worked well for us. No doubt there are others.
Well, how about no statements? You might want to look into an ORM to handle this for you...
Some databases have proprietary extensions that do exactly this.
I agree that the syntax of INSERT and UPDATE could be more consistent, but this is just a fact of life now -- it ain't gonna change now. For many scenarios, the best option is your "whole new way": use an object-relational mapping library (or even a weak-tea layer like .NET DataSets) to abstract away the differences, and stop worrying about the low-level SQL syntax. Not a viable option for every application, of course, but it would allow you to just construct or update an object, call a Save method and have the library figure out the SQL syntax for you.
If you think about it, INSERT and UPDATE are exactly the same thing. They map field names to values, except the UPDATE has a filter.
By creating an associative array, where the key is the field name and the value is the value you want to assign to the field, you have your mapping. You just need to convert it to a the proper string format depending on INSERT or UPDATE.
You just need to create a function that will handle the conversion based on the parameters given.
SQL Server 2008:
MERGE dbo.MyTable AS T
USING
(SELECT
#mykey AS MyKey
#myval AS MyVal
) AS S
ON (T.MyKey = S.MyKey)
WHEN MATCHED THEN
UPDATE SET
T.MyVal = S.MyVal
WHEN NOT MATCHED THEN
INSERT (MyKey, MyVal)
VALUES (S.MyKey, S.MyVal)
MySQL:
INSERT (MyKey, MyVal)
INTO MyTable
VALUES({$myKey}, {$myVal})
ON DUPLICATE KEY UPDATE myVal = {$myVal}