I want to exclude the strings in the address column which start with the letters C, G or S.
I have tried this expression,
SELECT * FROM guest_list
WHERE address NOT LIKE ("C%" OR "F%" OR "G%");
and it gives me the warnings like this:
'Warning: truncated incorrect DOUBLE value: 'C%'
'Warning: truncated incorrect DOUBLE value: 'G%'
here is the script to create my table.
CREATE TABLE `guest_list` (
`id` int(11) NOT NULL,
`first_name` varchar(50) DEFAULT NULL,
`last_name` varchar(50) DEFAULT NULL,
`address` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `guest_list` VALUES (1001,'Jim','Dowd','Lewisham West and Penge'),
(1002,'Lyn','Brown','West Ham'),(1003,'Ann','Clwyd','Cynon Valley'),
(1004,'Nic','Dakin','Scunthorpe'),(1005,'Pat','Glass','North West Durham'),
(1006,'Kate','Hoey','Vauxhall'),(1007,'Mike','Kane','Wythenshawe and Sale East'),
(1008,'John','Mann','Bassetlaw'),(1009,'Joan','Ryan','Enfield North'),
(1010,'Cat','Smith','Lancaster and Fleetwood'),(1011,'Mark','Tami','Alyn and Deeside'),
(1012,'Keith','Vaz','Leicester East'),(1013,'Ian','Austin','Dudley North'),
(1014,'Liam','Byrne','Birmingham, Hodge Hill'),(1015,'Ann','Coffey','Stockport');
What is the correct way to do this with LIKE please (if one does not use regex)?
LIKE is standard operator for comparing a column value to another column value, or to a quoted string.
"C%" OR "F%" OR "G%" is not a quoted string, but a mathematical operation with the result 0, since all values are string (but not numerical) values and converted to zero.
Instead of using one LIKE operator, you have to use n LIKE operators, where n is the number of your conditions:
SELECT columns FROM guest_list
WHERE address NOT LIKE ("C%") AND address NOT LIKE("F%") AND address NOT LIKE("G%")
By default, LIKE conditions are case-insensitive, so if you want to filter only uppercase, you have to specify a binary collation, e.g. LIKE ("C%" collate latin1_bin)..
Related
Having a dict of structured_files variable as below;
structured_files = {'158795_1635509614542_20211029151335135_27.1943_38.4319.jpg': ['158795', '1635509614542', '20211029151335135', '27.1943', '38.4319'], '2773170_1635255851988_20211026164412576_27.1836_38.4777.jpg': ['2773170', '1635255851988', '20211026164412576', '27.1836', '38.4777'], '2777171_1635330525915_20211027132846547_27.1875_38.4720.jpg': ['2777171', '1635330525915', '20211027132846547', '27.1875', '38.4720'], '2779392_1635150026780_20211025112027410_27.1627_38.4724.jpg': ['2779392', '1635150026780', '20211025112027410', '27.1627', '38.4724'], '3724797_1634893471399_20211022120432057_27.1334_38.5426.jpg': ['3724797', '1634893471399', '20211022120432057', '27.1334', '38.5426'], '5218186_1635161250087_20211025142730572_27.0694_38.4943.jpg': ['5218186', '1635161250087', '20211025142730572', '27.0694', '38.4943'], '5347212_1634987405913_20211023141006566_27.0454_38.5138.jpg': ['5347212', '1634987405913', '20211023141006566', '27.0454', '38.5138'], '8174846_1635335281021_20211027144801672_27.1039_38.3572.jpg': ['8174846', '1635335281021', '20211027144801672', '27.1039', '38.3572'], '9179383_1635321573332_20211027105933968_27.1251_38.3576.jpg': ['9179383', '1635321573332', '20211027105933968', '27.1251', '38.3576']}
Trying to insert in to mysql db code is follows;
For Creation;
Qcreate1 = "CREATE TABLE data_11 (id_key LONGTEXT NOT NULL, name VARCHAR(50) NOT NULL, date VARCHAR(50) NOT NULL, sample VARCHAR(50) NOT NULL, coord_y VARCHAR(50) NOT NULL, coord_x VARCHAR(50) NOT NULL, created datetime NOT NULL, key_id int PRIMARY KEY NOT NULL AUTO_INCREMENT )"
For Inserting;
cols = list(structured_files.keys())
vals = list(structured_files.values())
Q1 = f"INSERT INTO data_11 {cols} values {vals}"
mycursor.execute(Q1)
It gives the error : mysql.connector.errors.ProgrammingError: 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '['158795_1635509614542_20211029151335135_27.1943_38.4319.jpg', '2773170_16352...' at line 1
Why is that ?
Okay, I tested this code to do what you want:
Q1 = "INSERT INTO data_11 (id_key, name, date, sample, coord_y, coord_x) VALUES (%s, %s, %s, %s, %s, %s)"
for id_key, values in structured_files.items():
cursor.execute(Q1, [id_key] + values)
cnx.commit()
Tips:
Write the column names explicitly in the INSERT statement. Learn the syntax for INSERT:
INSERT INTO <table> (<columns>) VALUES (<values>)
Your id_key, the key in the dict, isn't a column name. It's one of the values, so it belongs in the VALUES clause.
This is the syntax for inserting one row. Once you get used to this, you can explore multi-row INSERT syntax.
Don't use f-strings to interpolate variables into the INSERT string, because that risks SQL injection flaws. Leave the values as placeholders as I showed, then pass the values separately as a list in the second argument to cursor.execute().
I have a situation where say a string has one replaceable character.. For ex..
Thi[$] is a strin[$] I am [$]ew to Or[$]cle
Now I need to replace the [$] with s,g,n,a
Respectively...
How can I do that? Please help.
There is a special PL/SQL function UTL_LMS.FORMAT_MESSAGE:
You can use use it in your INLINE pl/sql function:
with function format(
str in varchar2
,s1 in varchar2 default null
,s2 in varchar2 default null
,s3 in varchar2 default null
,s4 in varchar2 default null
,s5 in varchar2 default null
,s6 in varchar2 default null
,s7 in varchar2 default null
,s8 in varchar2 default null
,s9 in varchar2 default null
,s10 in varchar2 default null
) return varchar2
as
begin
return utl_lms.format_message(replace(str,'[$]','%s'),s1,s2,s3,s4,s5,s6,s7,s8,s9,10);
end;
select format('Thi[$] is a strin[$] I am [$]ew to Or[$]cle', 's','g','n','a') as res
from dual;
Result:
RES
-------------------------------------
This is a string I am new to Oracle
Here is a hand-rolled solution using a recursive WITH clause, and INSTR and SUBSTR functions to chop the string and inject the relevant letter at each juncture.
with rcte(str, sigils, occ) as (
select 'Thi[$] is a strin[$] I am [$]ew to Or[$]cle' as str
, 'sgna' as sigils
, 0 as occ
from dual
union all
select substr(str, 1, instr(str,'[$]',1,1)-1)||substr(sigils, occ+1, 1)||substr(str, instr(str,'[$]',1,1)+3) as str
, sigils
, occ+1 as occ
from rcte
where occ <= length(sigils)
)
select *
from rcte
where occ = length(sigils)
Here is a working demo on db<>fiddle.
However, it looks like #sayanm has provided a neater solution.
Consider this method that lets the lookup values be table-based. See the comments within. The original string is split into rows using the placeholder as a delimiter. Then the rows are put back together using listagg, joining on it's order to the lookup table.
Table-driven using as many placeholders as you want. The order matters though of course just as with the other answers.
-- First CTE just sets up source data
WITH tbl(str) AS (
SELECT 'Thi[$] is a strin[$] I am [$]ew to Or[$]cle' FROM dual
),
-- Lookup table. Does not have to be a CTE here, but a normal table
-- in the database.
tbl_sub_values(ID, VALUE) AS (
SELECT 1, 's' FROM dual UNION ALL
SELECT 2, 'g' FROM dual UNION ALL
SELECT 3, 'n' FROM dual UNION ALL
SELECT 4, 'a' FROM dual
),
-- Split the source data using the placeholder as a delimiter
tbl_split(piece_id, str) AS (
SELECT LEVEL AS piece_id, REGEXP_SUBSTR(t.str, '(.*?)(\[\$\]|$)', 1, LEVEL, NULL, 1)
FROM tbl T
CONNECT BY LEVEL <= REGEXP_COUNT(t.str, '[$]') + 1
)
-- select * from tbl_split;
-- Put the string back together, joining with the lookup table
SELECT LISTAGG(str||tsv.value) WITHIN GROUP (ORDER BY piece_id) STRING
FROM tbl_split ts
LEFT JOIN tbl_sub_values tsv
ON ts.piece_id = tsv.id;
STRING
--------------------------------------------------------------------------------
This is a string I am new to Oracle
Can I lower the elements in an array column like I can a varchar or text column?
SELECT * FROM a_tbl a
WHERE LOWER(%(uw)s) = ANY (a.n_lst) -- how to lower?
OR LOWER(a.x) = LOWER(%(uw)s)
I saw in the documentation that I could use citext as my datatype. I might try to alter my table if there isn't a way to use LOWER
a_tbl
-----
id SERIAL PRIMARY KEY
n_lst TEXT[]
x VARCHAR(50)
You can do like below:
select lower('Jonh') = any(lower(n_lst::text)::text[]) from a_tbl;
How to lowercase postgresql array?
SELECT * FROM a_tbl a
WHERE LOWER(%(uw)s) ILIKE ANY (a.n_lst) -- how to lower?
OR LOWER(a.x) = LOWER(%(uw)s)
I am using SDO_NN operator to find the nearest hydrant next to a building.
Building:
CREATE TABLE "BUILDINGS"
(
"NAME" VARCHAR2(40),
"SHAPE" "SDO_GEOMETRY")
Hydrant:
CREATE TABLE "HYDRANTS"
( "NAME" VARCHAR2(10),
"POINT" "SDO_POINT_TYPE"
);
I have setup spatial indexes properly for buildings.shape and I run the query to get the nearest hydrant to the building 'Motel'
select b1.name as name, h.point.x as x, h.point.y as y from buildings b1, hydrants h where b1.name ='Motel' and
SDO_nn( b1.shape, MDSYS.SDO_GEOMETRY(2003,NULL, NULL,SDO_ELEM_INFO_ARRAY(1,1003,1),
SDO_ORDINATE_ARRAY( h.point.x,h.point.y)), 'sdo_num_res=1')= 'TRUE';
Here's the problem:
When I set the parameter sdo_num_res=1, I get zero tuples.
And when I make sdo_num_res=2, I get one tuple.
What is the reason for the weird behavior ?
Note: I am getting zero rows only when building.name= 'Motel', for all other tuples I am getting 1 row when sdo_num_res = 1
Edit:
Insert queries
Insert into buildings (NAME,SHAPE) values ('Motel',MDSYS.SDO_GEOMETRY(2003,NULL,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,1),MDSYS.SDO_ORDINATE_ARRAY(564,425,585,436,573,458,552,447)));
Insert into hydrants (name,POINT) values ('p57',MDSYS.SDO_POINT_TYPE(589,448,0));
To perform spatial comparisons between a point to a polygon, the SDO_GEOMETRY is defined with SDO_SRID=2001 and center set to a SDO_POINT_TYPE-> which we want to compare.
MDSYS.SDO_GEOMETRY(2001, NULL, SDO_POINT_TYPE(-79, 37, NULL), NULL, NULL)
First of all, your query does not do what you say it does: it actually returns the nearest building called "Motel" from any of your hydrants. To do what you want (i.e. the opposite) you need to reverse the order of the arguments to SDO_NN: all spatial operators search the first argument, using the value of the second argument.
Then the insert into your HYDRANTS table is wrong:
Insert into hydrants (name,POINT) values ('p57',MDSYS.SDO_POINT_TYPE(589,448,0));
The SDO_POINT_TYPE object is not designed to be used that way: it is only used inside the SDO_GEOMETRY type. The proper way is this:
insert into hydrants (name,POINT) values ('p57',sdo_geometry(2001, null, SDO_POINT_TYPE(589,448,null), null, null));
And of course you need to change your table definition accordingly.
Then your building is also incorrectly created: a polygon must always close, i.e. the last point must be the same as the first point. So the proper shape should be like this:
insert into buildings (NAME,SHAPE) values ('Motel', SDO_GEOMETRY(2003,NULL,NULL,SDO_ELEM_INFO_ARRAY(1,1003,1),SDO_ORDINATE_ARRAY(564,425,585,436,573,458,552,447,564,425)));
Here is the full example:
Create the tables:
create table buildings (
name varchar2(40) primary key,
shape sdo_geometry
);
create table hydrants(
name varchar2(10) primary key,
point sdo_geometry
);
Populate the tables:
insert into buildings (NAME,SHAPE) values ('Motel', SDO_GEOMETRY(2003,NULL,NULL,SDO_ELEM_INFO_ARRAY(1,1003,1),SDO_ORDINATE_ARRAY(564,425,585,436,573,458,552,447,564,425)));
insert into hydrants (name,POINT) values ('p57',sdo_geometry(2001, null, SDO_POINT_TYPE(589,448,null), null, null));
commit;
Confirm that the geometries are all correct:
select name, sdo_geom.validate_geometry_with_context (point, 0.05) from hydrants;
select name, sdo_geom.validate_geometry_with_context (shape, 0.05) from buildings;
Setup spatial metadata and create spatial indexes:
insert into user_sdo_geom_metadata (table_name, column_name, diminfo, srid)
values (
'BUILDINGS',
'SHAPE',
sdo_dim_array (
sdo_dim_element ('X', 0,1000,0.05),
sdo_dim_element ('Y', 0,1000,0.05)
),
null
);
commit;
create index buildings_sx on buildings (shape)
indextype is mdsys.spatial_index;
insert into user_sdo_geom_metadata (table_name, column_name, diminfo, srid)
values (
'HYDRANTS',
'POINT',
sdo_dim_array (
sdo_dim_element ('X', 0,1000,0.05),
sdo_dim_element ('Y', 0,1000,0.05)
),
null
);
commit;
create index hydrants_sx on hydrants (point)
indextype is mdsys.spatial_index;
Now Try the properly written query:
select h.name, h.point.sdo_point.x as x, h.point.sdo_point.y as y
from buildings b, hydrants h
where b.name ='Motel'
and sdo_nn(h.point, b.shape, 'sdo_num_res=1')= 'TRUE';
which returns:
NAME X Y
---------------- ---------- ----------
p57 589 448
1 row selected.
I am using DB2 LUW 9.5. In a field, I have a value like this one:
Test^test^^test^^^^test^^test^test
In a SELECT query, I would like to replace the duplicated ^ with only one ^. This would produce:
Test^test^test^test^test^test
The delimiter is known and static (can be hardcoded). Would you know a way to obtain the desired output using DB2 functions?
Thank you
You need one other character that can be used as delimiter, for example the pipe sign (|).
Let's say the table is defined as
create table myTable (
myColumn varchar(400)
);
Add a value for a test:
insert into myTable (myColumn) values
('Test^^^^^^^^test^^^^^^^test^^^^^^test^^^^^test^^^^test^^^test^^test^test');
Then do a smart replacement with use of the other delimiter
select replace(replace(replace(myColumn, '^^', '^|^'), '|^^', ''), '^|^', '^')
from myTable;
The result:
Test^test^test^test^test^test^test^test^test^test
Instead of using a one character delimiter you can use a string of which you are sure it will not occur in the values, for example 'xy'. The next query will give the same results:
select replace(replace(replace(myColumn, '^^', '^xy^'), 'xy^^', ''), '^xy^', '^')
from myTable;