No Changed Rows Produced by this mySQL update query. Why? - sql

I am at a loss this morning. Maybe my coffee was drugged? Simple problem- get the existing ids into this temp table for an export.
Tables like so:
Table person
+--------+-----------------------+
| id | email |
+--------+-----------------------+
| 142755 | xxxxxxx#xxxxxxxxx.com |
+--------+-----------------------+
Table no_dma
+--------+------------------------+
| person | email |
+--------+------------------------+
| 0 | xxxxxxx#xxxxxxxxx.com |
+--------+------------------------+
Query:
UPDATE
person, no_dma
SET no_dma.person = person.id
WHERE person.email = no_dma.email;
I have verified the existence of at least some matching email addresses in the two tables but the update produces
Query OK, 0 rows affected (9.31 sec)
Rows matched: 0 Changed: 0 Warnings: 0
Clearly I have a little dain bramamge today.
Help me out? What am I doing incorrectly?
// EDIT
Per comments below I made these queries:
mysql> select person, email from no_dma limit 0,1;
+--------+------------------------+
| person | email |
+--------+------------------------+
| 0 | tom_r1989#xxxxxxx.com
+--------+------------------------+
1 row in set (0.00 sec)
mysql> select email from no_dma where email = 'tom_r1989#xxxxxxx.com';
Empty set (0.00 sec)
mysql> select email from no_dma where TRIM(email) = 'tom_r1989#xxxxxxx.com';
Empty set (0.46 sec)
Both tables have email field stored as varchar with collation set to latin1_swedish_ci.
And this this query, WTH?
mysql> SELECT CONCAT('"',email,'"') from no_dma limit 0,3;
+-----------------------+
| CONCAT('"',email,'"') |
+-----------------------+
" |amjor308#xxx.com
" |utt#xxx.com
" |00000000#xxx.com
+-----------------------+
mysql> SELECT email from no_dma limit 0,3;
+--------------------+
| email |
+--------------------+
|+amjor308#xxx.com
|mutt#xxx.com
|000000000#xxx.com
+--------------------+
What is going on there? Looks like newlines but I thought TRIM() handled those?
mysql> SELECT TRIM(email) from no_dma limit 0,3;
+--------------------+
| TRIM(email) |
+--------------------+
|+amjor308#aol.com
|mutt#excite.com
|000000000#aol.com
+--------------------+
3 rows in set (0.00 sec)
UPDATE: FOUND ISSUE
import was done on a Windows generated CSV but mysqlimport was given arg
--lines-terminated-by='\n'
Reimported data works fine.
Sorry to have wasted folks time.

Table no_dma has a trailing space. The data is not the same.
Edit:
SET ANSI_PADDING?
Is it really a space: is ASCII 160
What does a hash or checksum of each value reveal?
What are the string lengths?

The statement is fine, I think. B/c I tested it and it worked.

Related

tidb cannot fuzzy query with like '_' for double byte character?

In my program, I want to lookup "测试" with
select * from test where name like '测_';
After my test, I found that MySQL can, but tidb can't?
This seems to be working fine for me. What character set is your table, column and connection? What TiDB version are you using?
mysql> CREATE TABLE t1 (id char(2) character set utf8mb4 primary key);
Query OK, 0 rows affected (0.18 sec)
mysql> INSERT INTO t1 VALUES('测试'),('测x');
Query OK, 2 rows affected (0.12 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM t1 WHERE id LIKE '测_';
+--------+
| id |
+--------+
| 测x |
| 测试 |
+--------+
2 rows in set (0.11 sec)
mysql> SELECT tidb_version();
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tidb_version() |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Release Version: v5.4.0
Edition: Community
Git Commit Hash: 55f3b24c1c9f506bd652ef1d162283541e428872
Git Branch: heads/refs/tags/v5.4.0
UTC Build Time: 2022-01-25 08:39:26
GoVersion: go1.16.4
Race Enabled: false
TiKV Min Version: v3.0.0-60965b006877ca7234adaced7890d7b029ed1306
Check Table Before Drop: false |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.11 sec)

How can I update a list attribute in aql (aerospike)?

I have an aql table that looks like this:
| id | range
+---------------+-----------------------------------------------------
| "testId" | LIST('[{"start":"1000", "end":"2999"}]') |
+---------------+-----------------------------------------------------
I've been trying to unsuccessfully update the range using aql.
I tried this command:
insert into dsc.testTable (pk,'range')
values ('testId', LIST('[{"start":"500", "end":"1000"}]'))
But no luck. Help?
In your command, replace LIST with JSON.
See my example on namespace test, set demo below:
aql> insert into test.demo (pk,'range') values ('testId', json('[{"start":"500", "end":"1000"}]'))"
OK, 1 record affected.
aql> select * from test.demo where pk='testId'
+-----------------------------------------+
| range |
+-----------------------------------------+
| LIST('[{"start":"500", "end":"1000"}]') |
+-----------------------------------------+
1 row in set (0.001 secs)
OK

Clarifications about some SQL Injection commands

I'm struggling with a CTF(Capture The Flag) Web Challange on hackthebox, not being an expert in penetration testing I'm asking your help to explain me (with some comments) some commands used to reach the solution, expecially about the syntax and logic of the commands themselves. (A reference to the commands can be found here (click me), so you have the whole situation very clear).
I ask you to be very detailed, even on things that may seem trivial.
Leaving aside the base64 encoding (that I understand) I need to understand these commands and their related parameters (syntax and logic of the commands):
1th: {"ID":"1"}
2nd: {"ID": "1' or 1-- -"}
3rd: {"ID": "-1' union select * from (select 1)table1 JOIN (SELECT 2)table2 on 1=1-- -"}
About the 3rd command, I saw the same command but with an alteration of the table names, like this:
{"ID": "-1' union select * from (select 1)UT1 JOIN (SELECT 2)UT2 on 1=1-- -"}
What is the difference? Is the name given to the tables in the query irrelevant?
If you need further clarification or I haven't made myself clear, just tell it and I'll try to help you. Thank you in advance.
The stage of hacking is: recon, scanning, gaining access, maintaining access, and clearing tracks. Basically it's just obtain information, then do something with that information It seems that this SQL injection learning module is used to teach how to obtain information about the current system.
The basic of SQL injection is inserting SQL code/command/syntax. It's usually done in the WHERE clause (because webapp often have search feature, which is basically retrieving user input and inserting it on the where clause.
For example, the simplest vulnerability would be like this (assuming MySQL and PHP):
SELECT * FROM mytable WHERE mycolumn='$_GET[myparam]'
Payload is what you put inside the parameter (ex: myparam) to do SQL injection.
With such query, you can inject payload 1' OR 1=1 to test for SQL injection vulnerability.
1st payload
1st payload is used to check if there is an injection point (parameter that can be injected) or not.
If you change the parameter and there is a change on the output, then it means there is an injection point.
Otherwise there is no injection point
2nd payload
2nd payload is used to check if the target app have SQL injection vulnerability or not (would the app sanitize user's input or not).
If the app shows all output, then it means the app have SQL injection vulnerability. Explanation: because the query sent to RDBMS would become something like this
Before injection:
SELECT col1, col2, ... colN FROM mytable WHERE col1='myparam'
After injection:
SELECT col1, col2, ... colN FROM mytable WHERE col1='1' or 1-- -'
Please note that in MySQL, -- (minus-minus-space) is used to mark inline comment. So the actual query would be: SELECT col1, col2, ... colN FROM mytable WHERE col1='1' or 1
3rd payload
3rd payload is used to check how many column the query would SELECT. To understand this you have to understand subquery, join, and union (do a quick search, it's a very basic concept). The name or the table alias is not important (UT1 or UT2), it's just identifier so that it's not identical with current table alias.
If the query succeed (no error, the app display output), then it means the app query SELECTs 2 columns
If the query failed, then it means it's not 2 column, you can change the payload to check for 3 columns, 4 columns, etc...
Example for checking if SELECT statement have 3 columns:
-1' union select * from (select 1)UT1 JOIN (SELECT 2)UT2 on 1=1 JOIN (SELECT 3)UT3 on 1=1 -- -
Tips: when learning about SQL injection, it's far easier to just type (or copy-paste) the payload to your SQL console (use virtual machine or sandbox if the query is considered dangerous).
Edit 1:
basic explanation of subquery and union
Subquery: It's basically putting a query inside another query. Subqueries may be inserted in SELECT clause, FROM clause, and WHERE clause.
Example of subquery in FROM clause:
select * from (select 'hello','world','foo','bar')x;
Example of subquery in WHERE clause:
select * from tblsample t1 where t1.price>(select avg(t2.price) from tblsample t2);
Union: concatenating select output, example:
tbl1
+----+--------+-----------+------+
| id | name | address | tele |
+----+--------+-----------+------+
| 1 | Rupert | Somewhere | 022 |
| 2 | John | Doe | 022 |
+----+--------+-----------+------+
tbl2
+----+--------+-----------+------+
| id | name | address | tele |
+----+--------+-----------+------+
| 1 | AAAAAA | DDDDDDDDD | 022 |
| 2 | BBBB | CCC | 022 |
+----+--------+-----------+------+
select * from tbl1 union select * from tbl2
+----+--------+-----------+------+
| id | name | address | tele |
+----+--------+-----------+------+
| 1 | Rupert | Somewhere | 022 |
| 2 | John | Doe | 022 |
| 1 | AAAAAA | DDDDDDDDD | 022 |
| 2 | BBBB | CCC | 022 |
+----+--------+-----------+------+
Edit 2:
further explanation on 3rd payload
In mysql, you can make a 'literal table' by selecting a value. Here is an example:
MariaDB [(none)]> SELECT 1;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.00 sec)
MariaDB [(none)]> SELECT 1,2;
+---+---+
| 1 | 2 |
+---+---+
| 1 | 2 |
+---+---+
1 row in set (0.00 sec)
MariaDB [(none)]> SELECT 1 firstcol, 2 secondcol;
+----------+-----------+
| firstcol | secondcol |
+----------+-----------+
| 1 | 2 |
+----------+-----------+
1 row in set (0.00 sec)
The purpose of making this 'literal table' is to check how many column the SELECT statement that we inject have. For example:
MariaDB [(none)]> SELECT 1 firstcol, 2 secondcol UNION SELECT 3 thirdcol, 4 fourthcol;
+----------+-----------+
| firstcol | secondcol |
+----------+-----------+
| 1 | 2 |
| 3 | 4 |
+----------+-----------+
2 rows in set (0.07 sec)
MariaDB [(none)]> SELECT 1 firstcol, 2 secondcol UNION SELECT 3 thirdcol, 4 fourthcol, 5 fifthcol;
ERROR 1222 (21000): The used SELECT statements have a different number of columns
As shown above, when UNION is used on two select statement with different number of column, it'll throw an error. Therefore, you can get how many column a SELECT statement when it DOESN'T throw an error.
So, why don't we just use SELECT 1, 2 to generate a 'literal table' with 2 column? That's because the application's firewall block the usage of comma. Therefore we must go the roundabout way and make 2 columned 'literal table' with JOIN query SELECT * FROM (SELECT 1)UT1 JOIN (SELECT 2)UT2 ON 1=1
MariaDB [(none)]> SELECT * FROM (SELECT 1)UT1 JOIN (SELECT 2)UT2 ON 1=1;
+---+---+
| 1 | 2 |
+---+---+
| 1 | 2 |
+---+---+
1 row in set (0.01 sec)
Additional note: MariaDB is the 'free version' of MySQL (since MySQL was sold and made proprietary). MariaDB maintain more or less the same syntax and command as MySQL.

How to get info from VARCHAR column and create new column out of it

I have a problem that I can't figure out.
I have the table where it has column template_name,
in every template, it ends with _US, _EE (aka country).
I have to get that part to a new column that is Country.
Example data:
Template_name Country
Party_package_US US or USA
PARTY_Package_GB GB or England
Random_temp_DE DE or Germany
The output to the new column can be just the three last characters.
I don't know what kind of query I have to do to get that result.
Okay now, what can I do get that result to the new column in table?
UPDATE #silverpop_header
SET MARKET_AREA = a.template_name
FROM #silverpop_header pop
join dw.f_CRM a
ON pop.template_name = a.TEMPLATE_NAME
left join (
select
RIGHT(RTRIM(Template_name), 2) country
from dw.f_CRM )
It is on Sybase
If you just need the last two characters
SELECT
SUBSTRING(Template_name,-2) AS 'Country'
FROM TABLE;
EDIT:
Or as mentioned in the comments:
SELECT
RIGHT(Template_name,2) AS 'Country'
FROM TABLE;
Another way to handle non-2-digit country code.
SELECT Template_name, SUBSTRING_INDEX(Template_name, '_', -1) Country
FROM tbl;
To make this as a full demo. Let me post the full SQLs and output:
SQL:
-- Data prepraration
create table tbl(template_name varchar(200));
insert into tbl values
('Party_package_US'),
('PARTY_Package_GB'),
('Random_temp_DE');
SELECT * FROM tbl;
-- Needed query
SELECT Template_name, SUBSTRING_INDEX(Template_name, '_', -1) Country
FROM tbl;
Output:
mysql> SELECT * FROM tbl;
+------------------+
| template_name |
+------------------+
| Party_package_US |
| PARTY_Package_GB |
| Random_temp_DE |
+------------------+
3 rows in set (0.00 sec)
mysql>
mysql> -- Needed query
mysql> SELECT Template_name, SUBSTRING_INDEX(Template_name, '_', -1) Country
-> FROM tbl;
+------------------+---------+
| Template_name | Country |
+------------------+---------+
| Party_package_US | US |
| PARTY_Package_GB | GB |
| Random_temp_DE | DE |
+------------------+---------+
3 rows in set (0.00 sec)
mysql>
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.7.8-rc |
+-----------+
1 row in set (0.00 sec)

Selecting records in groups by date - possible?

I don't think there is an elegant way to do this, but here goes. Database contains 5000 records with timestamps of 2 years. I need to pull the records under each day of the year.
So it looks like..
09/09/2009 - record938, record2, record493
09/10/2009 - record260, record485, record610
...etc
I cannot use GROUP BY. There are duplicates and that's OK. I need to show them.
Is this possible? PHP/MySQL?
One way of doing it is looping through every day of the year and doing a query with "WHERE DAY(created_at)..." but obviously this isn't elegant.
HOW can I do this? I posted this question before without a satisfactory answer (answer was what I just stated above)
MySQL has the group_concat() aggregate function:
SELECT date(rec_time), group_concat(rec_id)
FROM records GROUP BY date(rec_time);
Will return all rec_id values from table joined by commas, for each date. If you want a separator other than , use group_concat(some_column SEPARATOR '-')
Example
For example if your table looks like:
+--------+---------------------+
| rec_id | rec_time |
+--------+---------------------+
| 1 | 2009-11-28 10:00:00 |
| 2 | 2009-11-28 20:00:00 |
| 3 | 2009-11-27 15:00:00 |
| 4 | 2009-11-27 07:00:00 |
| 5 | 2009-11-28 08:00:00 |
+--------+---------------------+
Then this query gives:
mysql> SELECT date(rec_time), group_concat(rec_id)
-> FROM records GROUP BY date(rec_time);
+----------------+----------------------+
| date(rec_time) | group_concat(rec_id) |
+----------------+----------------------+
| 2009-11-27 | 3,4 |
| 2009-11-28 | 1,2,5 |
+----------------+----------------------+
Caveat
Beware that the result is limited by the group_concat_max_len system variable, which defaults to only 1024 bytes! To avoid hitting this wall, you should execute this before running the query:
SET SESSION group_concat_max_len = 65536;
Or more, depending on how many results you expect. But this value cannot be larger than max_allowed_packet