Reputation: 2036
I need to find if a string value exists in any column in my table. It's possible create automatically procedure or query in Firebird that perform this work without making explicit column names?
Column names can be find with this query:
select RDB$RELATION_FIELDS.rdb$field_name as NC from RDB$RELATION_FIELDS where RDB$RELATION_FIELDS.rdb$relation_name = MY_Table_name
I would use a procedure similar to that in Firebird:
SET TERM ^^ ;
CREATE PROCEDURE P_FINDSTRINGINTABLE (
STRTOFIND VarChar(255),
TBLNAME VarChar(255))
returns (
SQLCOMMAND VarChar(25000))
AS
DECLARE VARIABLE condSTR VARCHAR(8000);
DECLARE VARIABLE columnName VARCHAR(8000);
begin
sqlCommand = 'select * from '|| upper( :TBLNAME );
condSTR = '';
for select RDB$RELATION_FIELDS.rdb$field_name as NC from RDB$RELATION_FIELDS where RDB$RELATION_FIELDS.rdb$relation_name = upper( :TBLNAME )
into :columnName
do begin
condSTR = condSTR||columnName||' LIKE ''%'||STRTOFIND||'%'' OR ';
end
IF ( CHAR_LENGTH(condSTR) > 0 ) THEN
begin
condSTR = ' where ' || left(condSTR, CHAR_LENGTH (condSTR)-3) || ';';
sqlCommand = sqlCommand|| condSTR;
end
ELSE sqlCommand = sqlCommand||';' ;
end ^^
SET TERM ; ^^
I've created the right string SQL for my search. Now, if I execute this Firebird procedure, it returns the SQL command as string.
Are there methods to automatically execute the returned select?
Upvotes: 3
Views: 7355
Reputation: 1164
Here is the syntax, based on the above posts, to simply run a SELECT statement, without creating a stored procedure:
SET TERM ^ ;
EXECUTE BLOCK
RETURNS
( table_with_value varchar(200),
column_with_value varchar(200),
containing_value varchar(4000))
AS
declare variable all_tables varchar(200);
declare variable all_columns varchar(200);
declare variable all_values varchar(4000);
BEGIN
FOR SELECT
r.rdb$relation_name, f.rdb$field_name
from rdb$relation_fields f
JOIN RDB$FIELDS ON (RDB$FIELDS.RDB$FIELD_NAME = f.RDB$FIELD_SOURCE)
join rdb$relations r on f.rdb$relation_name = r.rdb$relation_name
and r.rdb$view_blr is null
and (r.rdb$system_flag is null or r.rdb$system_flag = 0)
and RDB$FIELDS.RDB$FIELD_TYPE in (37, 40)
and RDB$FIELDS.RDB$FIELD_TYPE is not null
order by 1, f.rdb$field_position INTO :all_tables, :all_columns
DO
BEGIN
FOR EXECUTE STATEMENT 'SELECT "' || all_columns || '" FROM "' || all_tables || '"'
INTO :all_values
DO
BEGIN
IF (all_Values like '%SEARCH_VALUE%') THEN
BEGIN
table_With_Value = all_Tables;
column_With_Value = all_Columns;
containing_value = all_Values;
SUSPEND;
END
END
END
END^
SET TERM ^ ;
Upvotes: 1
Reputation: 26
You can achieve something quite close to what you want, I believe, by using the EXECUTE STATEMENT
to create a view that would then return the values.
Example of what I mean:
sqlCommand = 'select * from '|| upper( :TBLNAME );
/* Rest of your code for creating the sqlCommand variable */
viewCommand = "RECREATE VIEW V_SEARCH_RESULTS AS " || sqlCommand;
EXECUTE STATEMENT viewCommand;
So basically your procedure P_FINDSTRINGINTABLE would NOT return any values, but would (re)create a view dynamically called V_SEARCH_RESULTS. All you would then have to do is select from this view to see the results.
Upvotes: 1
Reputation: 5741
If you need full text search in your DB, I suggest you to use dedicated search engine that integrates with Firebird. This is for performance reasons. Take a look at SphinxSearch or Solr engines.
Upvotes: 1