mysql insert nested select from other db truncates double values - mysql

I have a table in one database, call this db x. I have another database, call it y. I want to copy data from x.some_table to y.some_table. I don't want to do an exact copy of the table, because some columns don't make sense in database b. I use the following query:
INSERT INTO y.some_table (a_field) SELECT a_field FROM x.some_table;
a_filed in both tables is defined as DOULBE(17,0). If i run this:
USE y;
SELECT a_field FROM x;
Then I get output with full values --no floating-point truncation. However, if after insertion using the first query I showed, I get nothing but whole numbers in y's some_table.a_field. The floating-point remainders are truncated.
What am I doing wrong? Thanks.

Are you sure that the column is defined as DOUBLE(17,0) in both tables? Doesn't that specify 17 total digits with 0 after the decimal? If so you're select from table x should also have 0 decimal places. If its defined differently in x say DOUBLE(17,6) and you are trying to insert it into DOUBLE(17,0) then the decimals will be truncated I believe.

Not sure what is causing truncation .. you can make sure that you properly set the floating type .. if you think your table definition is OK, you can create a script to test it
for example, in PHP you could do something like -
$sql = "SELECT your_select_field FROM your_table";
$result = mysql_query($sql);
while($row = mysql_fetch_assoc($result)) {
$sql_ins = "INSERT INTO your_insert_table SET your_field = '".$row['your_select_field']."' ";
$res_ins = mysql_query($sql_ins);
}

Related

How do I make a database column a function of another column

I'm trying to make a database column which would be the percent of the value in another column
<?php
$sql = "ALTER TABLE inventorylist
ADD COLUMN percent DOUBLE
GENERATED ALWAYS AS (turnover/SUM(turnover)*100);";
?>
As already commented generated columns can only refer to the columns of the same row. But you could try a view including the calculation. Something along the lines of:
CREATE VIEW inventorylist_with_percent
AS
SELECT il1.*,
il1.turnover / (SELECT sum(il2.turnover)
FROM inventorylist il2) * 100 percent
FROM inventorylist il1;
I think it will safe to say let your code logic handle that task instead of pushing it to the database. Write a code that does the computation while inserting or while querying from the database.

"SELECT EXISTS" giving incorrect result, corrects upon resetting connection

I'm connected to a MySQL server on two different connections. On one of them, I can execute:
query = 'SELECT EXISTS(SELECT * FROM TABLE WHERE COLUMN = "VALUE")'
c.execute(query)
In: c.fetchall()[0][0]
Out: 1
Connected through a second machine, using identical values, I get the following:
query = 'SELECT EXISTS(SELECT * FROM TABLE WHERE COLUMN = "VALUE")'
c.execute(query)
In: c.fetchall()[0][0]
Out: 0
The only thing that seems to fix it is closing the connection and restarting it. It is causing some problems. Is there anything I can do to fix this?
Logically speaking, the same exists query with the same underlying data should return the same result on all machines. However, I see a problem with your query. You are using double quotes around VALUE, which you intend to be a string literal. This could be causing MySQL to view VALUE as an identifier (e.g. as a column). Try using single quotes instead:
query = "SELECT EXISTS (SELECT 1 FROM TABLE WHERE COLUMN = 'VALUE')"
c.execute(query)
In: c.fetchall()[0][0]

Searching for multiple values in 1 query

If I have a database having 2 fields, Roll no and name and I have a list (of n values) of roll numbers for which I have to search the corresponding names.
Can this be done using just one query in SQL or HQL?
SELECT name FROM [table] WHERE id IN ([list of ids])
where [list of ids] is for example 2,3,5,7.
Use the IN operator and separate your Roll no's by a comma.
SELECT name
FROM yourtable
WHERE [Roll no] IN (1, 2, 3, 4, etc)
You can use the IN statement as shown above.
There are a couple of minor issues with this. It can perform poorly if the number of values in the clause gets too large.
The second issue is that in many development environments you land up needing to dynamically create the query with a variable number of items (or a variable number of placeholders if using parameterised queries). While not difficult if does make your code look messy and mean you haven't got a nice neat piece of SQL that you can copy out and use to test.
But examples (using php).
Here the IN is just dynamically created with the SQL. Assuming the roll numbers can only be integers it is applying intval() to each member of the array to avoid any non integer values being used in the SQL.
<?php
$list_of_roll_no = array(1,2,3,4,5,6,7,8,9);
$sql = "SELECT FROM some_table WHERE `Roll no` IN (".implode(", ", array_map ('intval', $list_of_roll_no)).")";
?>
Using mysqli bound parameters is a bit messy. This is because the bind parameter statement expects a variable number of parameters. The 2nd parameter onwards are the values to be bound, and it expects them to be passed by reference. So the foreach here is used to generate an array of references:-
<?php
$list_of_roll_no = array(1,2,3,4,5,6,7,8,9);
if ($stmt = $mysqli->prepare("SELECT FROM some_table WHERE `Roll no` IN (".implode(",", array_fill(0, count($list_of_roll_no), '?')).")"))
{
$bind_arguments = [];
$bind_arguments[] = str_repeat("i", count($list_of_roll_no));
foreach ($list_of_roll_no as $list_of_roll_no_key => $list_of_roll_no_value)
{
$bind_arguments[] = & $list_of_roll_no[$list_of_roll_no_key]; # bind to array ref, not to the temporary $recordvalue
}
call_user_func_array(array($statement, 'bind_param'), $bind_arguments);
$statement->execute();
}
?>
Another solution is to push all the values into another table. Can be a temp table. Then you use an INNER JOIN between your table and your temp table to find the matching values. Depending on what you already have in place then this is quite easy to do (eg, I have a php class to insert multiple records easily - I just keep passing them across and the class batches them up and inserts them occasionally to avoid repeatedly hitting the database).

using float-type value in SQL commands

$query2 = mysqli_query($con, "SELECT * FROM third WHERE id2=$id2 AND divid=3.0");
this is my SQL command and it works well. but if i wnt to use divid=3.1 (some float in here) instad of 3.0 it mysqli_num_rows returns 0. And i am perfectly sure i have many divid=3.1 column in my database.
`$query2 = mysqli_query($con, "SELECT * FROM third WHERE id2=20 AND divid=3.1");` //this givs me mysqli_num_rows == 0;
Is there something different using float-type in SQL commands?
The difference with a FLOAT is that it's an approximate value. I just created a table with values 3 and 3.1, and when I tried querying for WHERE divid = 3.1 I didn't get any rows back either. I'm assuming that's because 3.1 ends up as something like 3.1000000000000001 or 3.0999999999999999.
Your options here are:
Change your table so the divid column is a DECIMAL type.
Cast divid to a DECIMAL when you use it in a WHERE clause:
SELECT * FROM third WHERE id2=20 AND CAST(divid AS DECIMAL(10,1))=3.1
Round divid when querying:
SELECT * FROM third WHERE id2=20 AND ROUND(divid, 1) = 3.1
I recommend the first option if it's not too late in the project to change a column type.
FLOAT and DOUBLE PRECISION data types have a rounding behavior by design. You can't expect them to behave like exact numeric values. See http://dev.mysql.com/doc/refman/5.6/en/problems-with-float.html
You should use DECIMAL (or its synonym NUMERIC) instead.
I tweeted about this last year: https://twitter.com/billkarwin/status/347561901460447232
If I had a dime for every time I've seen someone use FLOAT to store currency,
I'd have $999.997634. #ieee754jokes

JDBC prepareStatement doesn't work

I'm trying to use the prepareStatement function. The code is below. After it executes, it returns me a bunch of vlicense strings instead of the values.
When the code finishing the statement.setString(), the statement becomes:
select 'vlicense' from Vehicle
However, it needs to be:
select vlicense from Vehicle
without the quotation marks. Can anyone tell me what's the problem?
statement = oConnection.prepareStatement("select ? from Vehicle");
String tempString = "vlicense";
statement.setString(1, tempString);
resultSet = statement.executeQuery();
You can't use parameter markers for column names, table names, data type names, or basically anything that isn't data.
When you add a bind variable to a statement like this it is escaped, so that actual SQL string in your example would go to the database as "SELECT 'vlicense' FROM Vehicle', selecting a literal string instead of the column name you want.
You need to concatenate that variable column name into your SQL statement before you prepare it:
statement = oConnection.prepareStatement("SELECT " + vlicense + " FROM Vehicle");
Bind variables are really for query parameters as opposed to dynamic queries.
The ? can't be used to specify the fields, just to do some filters in your query like:
statement = conn.prepareStatement("select field from Vehicle where name=?");
In your case your query is built as:
select 'vlicense' from Vehicle
which means: GET ME A STRING 'vlicense' FOR EACH RECORD OF 'Vehicle'. And you'll get n repeated strings depending on the number of records in your table
It has nothing to do with jdbc, prepared-statements or mysql.
It's just a wrong sql statement.
If you type:
Select 'justanexample' from Vehicle
and the table contains 4 lines, you will get 4 times
'justanexample'
'justanexample'
'justanexample'
'justanexample'
as result.
You did not specify your the table structure, but I guess the
statement should somehow look like this:
select * from Vehicle where license = ?