Why can't I use regex in Sybase SQL - sql

I am using this version of Sybase -
Adaptive Server Enterprise/15.5/EBF 18164 SMP ESD#2/P/x86_64/Enterprise Linux.
When I try to run the below query I get an error saying Incorrect syntax near 'regexp'.
SELECT * FROM T1 WHERE C1 regexp '.*'
Can someone suggest an alternative if this is not supported in this version of ASE.

Try this way:
SELECT * FROM T1 WHERE C1 like '%.%'
or
SELECT * FROM T1 WHERE C1 like '%[.]%'

Naively, you could either construct a varchar(nn) of characters that you want to find, or conversely, know the set of valid characters and search for any NOT in that set.
declare #mySet varchar(255)
select #mySet = '%[' + char(128) + char(129) + ... + ']%'
-- OR
select #mySet = '%[^A-Z0-9_-#.]%' -- for example, case insensitive
-- then
select * from T where C like #mySet

Related

SQL SELECT rows in a table if the given condition is a substring of the column data with a separator ';' between the substrings

I am trying to get rows from the table Mails if the column [To] has the mail abc#mail.
The simple solution would be Select * from Mails where [To] = 'abc#mail'
But the thing is [To] column has data like 123#mail;abc#mail;aabc#mail etc separated by semicolons
where To is multiple emails sent
I know I could do something like Select * from Mails where [To] like '%abc#mail%' but that won't solve the problem if the given mail is a substring of another mail. I thought of a split string solution
I have a split_string function like this,
CREATE FUNCTION [dbo].[split_string]
(
#string_value NVARCHAR(MAX),
#delimiter_character CHAR(1)
)
RETURNS #result_set TABLE(splited_data NVARCHAR(MAX)
)
BEGIN
DECLARE #start_position INT,
#ending_position INT
SELECT #start_position = 1,
#ending_position = CHARINDEX(#delimiter_character, #string_value)
WHILE #start_position < LEN(#string_value) + 1
BEGIN
IF #ending_position = 0
SET #ending_position = LEN(#string_value) + 1
INSERT INTO #result_set (splited_data)
VALUES(SUBSTRING(#string_value, #start_position, #ending_position - #start_position))
SET #start_position = #ending_position + 1
SET #ending_position = CHARINDEX(#delimiter_character, #string_value, #start_position)
END
RETURN
END
which would return splitted string of a single data in a column and the function is working fine.
I tried executing the query
Select *
from Mails
where 'abc#mail' in (
Select *
from dbo.split_string((SELECT [To] FROM Mails) , ';')
)
which is throwing the error:
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression.
I need help proceeding from here. I am using Microsoft SQL Server 2014.
TL;DR;
Here is the query that you want
SELECT *
FROM dbo.Mails AS m
WHERE EXISTS (
SELECT *
FROM dbo.split_string(m.[To], ';') s
WHERE s.splited_data = 'abc#mail'
)
I recommend the splitting approach. Any character lookup will have to account the variability of the semi-colons, whereas splitting it out will handle the ambiguity of where the semi-colons are, and then you can do a direct equality check. If you wanted to take it a step further and look for additional [To] addresses you can just add an IN clause like this and SQL Server doesn't have to do much more work and you get the same results.
SELECT *
FROM dbo.Mails AS m
WHERE EXISTS (
SELECT *
FROM dbo.split_string(m.[To], ';') s
WHERE s.splited_data IN ('abc#mail', 'def#mail')
)
My answer is fairly similar to #Kitta answer in that we split the data out, and #Kitta is correct about the IN clause, but while their answer will work it will require you grouping your data back together to get a singular answer. Using the EXISTS clause will bypass all of that for you and only give you the data from the original table. That being said, please mark #Kitta as the answer if their answer works just as well for you.
Here is the test setup that I used
DROP TABLE Mails
GO
CREATE TABLE Mails
([To] VARCHAR(3000))
INSERT INTO dbo.Mails
(
[To]
)
VALUES
('123#mail;abc#mail;aabc#mail')
,('nottheone#mail.com')
,('nottheone#mail.com;Overhere#mail.com')
,('aabc#mail;ewrkljwe#mail')
,('ewrkljwe#mail')
GO
DROP FUNCTION [split_string]
GO
CREATE FUNCTION [dbo].[split_string]
(
#string_value NVARCHAR(MAX),
#delimiter_character CHAR(1)
)
RETURNS #result_set TABLE(splited_data NVARCHAR(MAX)
)
BEGIN
DECLARE #start_position INT,
#ending_position INT
SELECT #start_position = 1,
#ending_position = CHARINDEX(#delimiter_character, #string_value)
WHILE #start_position < LEN(#string_value) + 1
BEGIN
IF #ending_position = 0
SET #ending_position = LEN(#string_value) + 1
INSERT INTO #result_set (splited_data)
VALUES(SUBSTRING(#string_value, #start_position, #ending_position - #start_position))
SET #start_position = #ending_position + 1
SET #ending_position = CHARINDEX(#delimiter_character, #string_value, #start_position)
END
RETURN
END
GO
SELECT *
FROM dbo.Mails AS m
WHERE EXISTS (
SELECT *
FROM dbo.split_string(m.[To], ';') s
WHERE s.splited_data = 'abc#mail'
)
and it returns the correct row of '123#mail;abc#mail;aabc#mail'
You can't pass a multi-row subquery as an argument to the dbo.split_string function. Try to join your table function to the Mails table:
SELECT DISTINCT ms.*
FROM Mails AS ms
CROSS APPLY dbo.split_string(ms.[To], ';') AS s
WHERE s.splited_data LIKE 'abc#mail'
If you can ubgrade your SQL Server up to 2016 (13.x), you can use built-in STRING_SPLIT table function instead of custom dbo.split_string.
Alternatively, you can achieve your goal with brute force and break down the comparison into simple terms such as follows:
SELECT *
FROM Mails
WHERE
[To] LIKE 'abc#mail'
OR [To] LIKE '%;abc#mail;%'
OR [To] LIKE 'abc#mail;%'
OR [To] LIKE '%;abc#mail'
It might not be the best way, but it's pretty simple and doesn't require a split function.
You can use CHARINDEX() function.
select * from Mails where CHARINDEX('abc#mail.com', To) > 0
The CHARINDEX function checks for a substring within a given string and returns a value greater than zero if it is found. Here your string to search (substring) would be 'abc#mail.com' and the main string from where to search would be the "To" column.
More information about CHARINDEX() function can be found at below link
https://www.techonthenet.com/sql_server/functions/charindex.php#:~:text=SQL%20Server%3A%20CHARINDEX%20Function%201%20Description.%20In%20SQL,use%20the%20CHARINDEX%20function%20in%20SQL%20Server%20%28Transact-SQL%29.

SQL LIKE Statment that applies on everything up to a certain character

My database contains a column for "website" with the following data:
foo1.web.com
foo2.gov
doo3.shoo.net
baa.com
baa2.shoo.com
I am looking to do a select statement that grabs everything like the variable but only up to the first period, I want to ignore everything after the period:
DELCARE #variable varchar(MAX);
SET #variable = 'oo';
SELECT * WHERE website LIKE '%' + #variable + '%' --(but only apply like statement up to the first .)
So what I would get back would be:
foo1.web.com
foo2.gov
doo3.shoo.net
but it would leave out
baa2.shoo.com
Thanks for the help in advance!
EDIT:
Using SQL Server
For SQL Server, you can look at only the left N characters of your URL for oo. You would get the left N characters by using LEFT and CHARINDEX to find the first .
SELECT *
FROM #table
WHERE LEFT(val, CHARINDEX('.', val)) LIKE '%'+#variable+'%'
Just another option
Example
Declare #YourTable Table ([website] varchar(50))
Insert Into #YourTable Values
('foo1.web.com')
,('foo2.gov')
,('doo3.shoo.net')
,('baa.com')
,('baa2.shoo.com')
DECLARE #variable varchar(MAX);
SET #variable = 'oo';
Select *
from #YourTable
where charindex('.',website+'.') > nullif(charindex(#variable,website),0)
Returns
website
foo1.web.com
foo2.gov
doo3.shoo.net
Let's say the column you search in named site, then I believe you can use something like this:
SELECT *
FROM website
WHERE `site` LIKE '%oo%' AND INSTR(`site`, 'oo')<INSTR(`site`, '.');

Query filter delphi firedac Firebird database

I´m migrating a database from SQLITE to Firebird, but now my query doesn't work.
What am I doing wrong? Is there a reason?
frmDados.Clientes.Close();
frmDados.Clientes.SQL.Text :=
'SELECT * FROM CLIENTES ' +
'WHERE (nomecliente like :d1) '+
'order by nomecliente asc';
frmDados.Clientes.Params.ParamByName('d1').AsString := '%' + Edit1.text + '%';
frmDados.Clientes.OpenOrExecute();
Firebird dose not support case insensitive queries.
Query_Case_Insensitive.html
Consider these options
select * from "abc_table" where "Some_Field" = 'Abc'
select * from "abc_table" where "Some_Field" like 'Abc'
select * from "abc_table" where "Some_Field" containing 'Abc'
select * from "abc_table" where upper("Some_Field") = 'ABC'
Equals (=) and *like * both perform case sensitive matches
*containing * is case insensitive, but will also match 'abcd'
upper() works, but will not use an index and, therefore, will read every record in the table
Equals (=) is the fastest because it uses an index (if available)

Oracle LIKE-wildcard in inner SELECT query

In SQL Server T-SQL I used to use the scenario like this
SELECT .. FROM .. WHERE sometable.eng LIKE (SELECT tmpcolumn FROM tmptable WHERE tmpID = #counter) + '%';
How to pass LIKE (subquery) + '%' in Oracle correcly?
Does it actually work for Oracle 11g+ or not?
.. smth LIKE (SELECT .. FROM ..) + '%';
The underscore _ for fixed length doesn't fit my needs, so % only.
Oracle uses || for string concatenation, not +. So it should be:
smth LIKE (SELECT .. FROM ..) || '%'
This seems like such an odd formulation. Just as a note, I would write the query as:
SELECT ..
FROM ..
WHERE EXISTS (SELECT 1
FROM tmptable
WHERE tmpID = #Counter AND
sometable.eng LIKE tmpcolumn || '%'
);
Putting a subquery between the keyword LIKE and the wildcard makes the query harder to read (at least for me).

SELECT statement having where clause with dynamic condition

I have a small select query which picks data from a table as per the parameter passed to a procedure.
DECLARE #flgParam bit
.
.
SELECT *
FROM tablename
WHERE flgRequired like <If #flgparam is 0 then 1 or zero , Else 1>
what is the best way to construct the where clause
I'm thinking something like this:
SELECT *
from tablename
where #flgparam is null or #flgcolumnval = #flgparam;
#flgparam is declared as a bit, so it can only take on the values of NULL, 0, and 1.
EDIT:
I'm trying to understand the logic. Adapted for the right names:
SELECT *
from sample
where (#flgparam = 0 and flgRequired is not null) or
(coalesce(#flgparam, 1) = 1 and flgRequired = 1)
The like is unnecessary; you can do strict equality.
A bit rough, but it should work, based on requirements:
select
S.itemname
,S.flgrequired
from
sample S
where
(S.flgRequired >= #flgParam)
Tested on sqlfiddle.
You cant use variables to substitute columns in the querys, to achieve that you should create your query as a string #QUERY and execute it using exec #QUERY