When I do the query below from a mysql console it works fine but when I wrap into perl/DBI I get:
DBD::mysql::st execute failed: Unknown column 'AR_email' in 'field list'
Here is the query:
my $q = "SELECT SUBSTRING(AR_email, LOCATE('#', AR_email) + 1) AS domain
FROM carrier
WHERE AR_email IS NOT NULL
AND SUBSTRING(AR_email, LOCATE('#', AR_email) + 1) =?";
my $sth=$dbh->prepare($q);
$sth->execute($domain);
Any idea how I can fix this?
The problem here is unintented string interpolation.
You are using double quotes (") when assigning the query string to $q, but it contains an arobas (#), which is interpolated.
So $q actually ends up containing:
SELECT SUBSTRING(AR_email, LOCATE(', AR_email) + 1) AS domain
FROM carrier
WHERE AR_email IS NOT NULL
AND SUBSTRING(AR_email, LOCATE(', AR_email) + 1) =?
If you were running this under use warnings, you would get this message:
Possible unintended interpolation of #' in string
One way to solve this is to define the query as a litteral string, for example:
my $q = q/SELECT SUBSTRING(AR_email, LOCATE('#', AR_email) + 1) AS domain
FROM carrier
WHERE AR_email IS NOT NULL
AND SUBSTRING(AR_email, LOCATE('#', AR_email) + 1) =?/;
Moral of the story:
use double quotes only when you do want string interpolation
always use strict; use warnings;
Related
I have tbl which include 2 columns: title and params, the values are like the following:
- title: {"Teaching"}
- params:
{ "ufield926":"34",
"ufield927":"Sud",
"ufield928":"Ara",
"ufield929":"Mecca",
"ufield930":"1\/1\/1983",
"ufield933":"011",
"ufield934":"Mub",
"ufield943":"SU\/HI\/14",
"ufield944":"Average",
"ufield946":"Female"
}
I want to extract the code after "ufield943": which is SU/HI/14 only and concatenate it with the value in title column to be like the following:
--> Teaching (SU/HI/14)
Here is the query I have tried:
SELECT title, CONCAT(title, "(", (select *,
substring(
params,
locate('ufield943', params) + 12,
locate('ufield944', params) - locate('ufield943', params) - 15
) FROM tbl), ")") AS title
FROM tbl;
I get the following error everytime I run the query
"Query Error: Error: ER_OPERAND_COLUMNS: Operand should contain 1 column(s)"
.
Mysql expects the exact field or value as SELECT statement fields. So, When you use an inner SELECT result as a field or value on outer SELECT, you have to return a specific value as a result.
So, You have to remove *, from your inner SELECT as the first step.
Another thing that you must do is removing title from outer SELECT. As your query CONCAT your title with the expected result, so there is no need of selecting title again.
So your query should like:
SELECT CONCAT(title, "(", (select
substring(
params,
locate('ufield943', params) + 12,
locate('ufield944', params) - locate('ufield943', params) - 21
) FROM master_code), ")") AS title
FROM master_code;
As a final note, This is not a good approach to saving data as JSON in MySQL and accessing data like this.
Thanks to MySQL (5.7.8 or upper), you can use MySQL JSON type features or handle this using a programing language.
Demo
I'm a beginner to SQL (as you'll soon be able to tell...) and I cannot for the life of me figure out how to best insert a simple JSON array of strings into a PostgreSQL table. I suspect the solution is quite easy but I've spent just a bit too long trying to puzzle it out on my own.
First I create the table:
CREATE TABLE test (
id serial PRIMARY KEY
my_array jsonb
);
Where the array is of type JSON. Insert some initial data:
INSERT INTO test (id, my_array) VALUES(1, '[]');
And now I want to update the myarray column with a JSON array using Node.js node-postgres. The array might look something like
const myArray = ['foo', 'bar', 'foobar\'s escaped character emporium'];
await db.none(
'UPDATE test ' +
`SET my_array = ${myArray} ` +
'WHERE id = 1'
);
This results in
error: syntax error at or near ","
Ok, so what if I do
await db.none(
'UPDATE test ' +
`SET my_array = "${myArray}" ` +
'WHERE id = 1'
);
I get
error: column "foo,bar,foobar's escaped character emporium" does not exist
and if I do
await db.none(
'UPDATE test ' +
`SET my_array = ${JSON.stringify(myArray)} ` +
'WHERE id = 1'
);
I get
ERROR error: syntax error at or near "["
Finally, if I do
await db.none(
'UPDATE test ' +
`SET my_array = '${JSON.stringify(myArray)}' ` +
'WHERE id = 1'
);
I end up with
stack=error: syntax error at or near "s"
I've also tried storing the data data as a native PostgreSQL array but I encounter similar problems:
CREATE TABLE test (
id serial PRIMARY KEY
my_array text ARRAY
);
INSERT INTO test (id, my_array) VALUES(1, '{}');
Then
const myArray = ['foo', 'bar', 'foobar\'s escaped character emporium'];
await db.none(
'UPDATE test ' +
`SET my_array = ${myArray} ` +
'WHERE id = 1'
);
gives
stack=error: syntax error at or near ","
Similar variations using JSON.stringify() and combinations of different quotes have proved fruitless as well. I kind of expected this approach to be less likely to work as PostgreSQL arrays are just a different format, but I was hoping there might be some kind of attempt at coercion. Reading through the documentation I can't spot any obvious way to convert a JSON array into the expected format for a PostgreSQL array.
Consider using a Parameterized query or Prepared statements.
That will help with you with qoutes and get protection against SQL injection as a bonus.
How can I write the following MySQL query in PostgreSQL syntax:
SELECT CONCAT(REPEAT(" ", (COUNT(parent.name) - 1)), cat.name) AS name
Thanks in advance!
The error here is that PostgreSQL doesn't allow double quotes " for literal strings (as per the SQL standard). You'll need to use single quotes '.
You also need to cast (COUNT(parent.name) - 1) to an integer, either using ::int (specific to Postgre) or CAST(... AS int).
Note that this may raise an integer out of range error if (COUNT(parent.name) - 1) is superior to 2147483647.
SELECT CONCAT(REPEAT(' ', (COUNT(parent.name) - 1)::int), cat.name) AS name
Note that you can also use || for string concatenation :
SELECT REPEAT(' ', (COUNT(parent.name) - 1)::int) || cat.name AS name
SELECT REPEAT(" ", (COUNT(parent.name) - 1)) || cat.name AS name
SQLFIDDLE
I have a normal SQL statement:
SELECT VALUE_ID, UF_CRM_TASK FROM b_uts_tasks_task
Now this returns a a different field everytime but they take the form of the following:
a:1:{i:0;s:7:"CO_2012";} or a:1:{i:0;s:5:"CO_12";} or a:1:{i:0;s:7:"CO_2017";}
Basically they're different everytime. What I need is to just get the number after the CO_ part. I have tried TRIM but because everything changes in the leading and trailing section I don't think this would work.
I have looked on Stack Overflow for a while and cannot find it. I know how to do it in PHP:
$data = $row['UF_CRM_TASK'];
$companyID = substr($data, strpos($data, "CO_") + 1);
$newCompanyID = preg_replace('/[^0-9.]+/', '', $companyID);
But not SQL. Thanks in advance
In MYSQL is a bit ugly:
/*SUBSTRING_INDEX BASED ON CO_ AND THE LAST " - in 2 SUBSTRINGS*/
SELECT `VALUE_ID`, SUBSTRING_INDEX(SUBSTRING_INDEX(`UF_CRM_TASK`, 'CO_', -1), '"', 1) AS `COMPANY_ID` FROM `b_uts_tasks_task`
In PHP you can just unserialize():
$data = unserialize($row['UF_CRM_TASK']);
$companyID = str_replace('CO_', '', $data[0]);
eg:
$data = unserialize('a:1:{i:0;s:5:"CO_12";}');
echo str_replace('CO_', '', $data[0]);
//==> 12
You need to use CharIndex and SubString (Microsoft SQL) or
This is the sample code I made for my Microsoft SQL server:
declare #companyIdString varchar(50) = 'a:1:{i:0;s:7:"CO_2012";}'
print 'Company ID in a string: ' + #companyIdString
print 'Find first position: ' + Cast(charindex('"CO_', #companyIdString) as varchar(2))
print 'Locate the second position (the last "): ' + Cast(charindex('"', #companyIdString, charindex('"CO_', #companyIdString)+4) as varchar(2))
print 'Extracted Company Id: ' + substring(#companyIdString,charindex('"CO_', #companyIdString)+4, charindex('"', #companyIdString, charindex('"CO_', #companyIdString)+4) - charindex('"CO_', #companyIdString) - 4)
select
#companyIdString as CompanyIdString,
substring(#companyIdString,charindex('"CO_', #companyIdString)+4, charindex('"', #companyIdString, charindex('"CO_', #companyIdString)+4) - charindex('"CO_', #companyIdString) - 4) as CompanyId
I also made the same code on a mySQL server:
set #companyIdString := 'a:1:{i:0;s:7:"CO_2012";}';
select
#companyIdString as CompanyIdString,
substring_index(substring_index(substring_index(#companyIdString, '"', 2), '"', -1), '_', -1) as CompanyId
The substring_index starts by locating the second " (string is now a:1:{i:0;s:7:"CO_2012), then it searches backward with the -1 to locate the first " (string is now CO_2012). And then it searches backward for the underscore (string is now 2012).
In ssis package I have String type variable V2 inside expression property i'm writing following sql query
"select * from mytable where date = " + #[System::StartTime]
But it is giving me an error :
The data types "DT_WSTR" and "DT_DATE" are incompatible for binary operator "+". The operand types could not be implicitly cast into compatible types for the operation. To perform this operation, one or both operands need to be explicitly cast with a cast operator.
Attempt to set the result type of binary operation ""select * from table where date = " + #[System::StartTime]" failed with error code 0xC0047080.
Even I have also tried with (DT_WSTR) #[System::StartTime]
still no luck any advice ?
You need to change data type of both StartTime variable and [date] field from the query to string.
Try this:
"select * from mytable where convert( varchar(10), [date], 120) = '" + SUBSTRING((DT_WSTR,50)#[System::StartTime],1, 10) + "'"
Which should return a proper query:
select * from mytable where convert( varchar(10), [date], 120) = '2013-05-22'
convert() will give you string like "2013-05-22". In my system (DT_WSTR) cast on #[System::StartTime] is returning string "2013-05-22 16:14:43", but if you have other settings, you'd have to construct the string from dateparts, if your default result would be for example "05/22/2013 16:14:43" due to other regional setting.
What is the verion of sql server you are using? and [date] field type exactly?