SQL statement to obfuscate phone nums in DB2 - db2

I am new to DB2 Express-C and am wondering if a SQL statement can be run in DB2 that can go thru all tables and change (could be scramble, replace, random, whatever) any 10-dgit phone numbers found. In a nut shell, do a global search and replace on all fields, in all tables, to obfuscate any phone numbers (private info).
I need to hand off a client's DB2 database (17 tables) to a software vendor to do some reporting but I have been tasked with making sure NO real phone numbers get exposed in the process. I'm sure there is a SQL statement that could handle a single table (then I could go into DB2 Control Center and run it 17x) but I am looking for a quick, clean way to 'prep' this DB before sending it out.
Thanks in advance to you DB2 gurus!
Mike

If you want to hide information in db2, you should use these functions:
ENCRYPT
DECRYPT_BIN
DECRYPT_CHAR
GETHINT
Or the IBM Database Encryption Expert
The functions are for varchar, and I think you have a int column, so it does not work.
However, you can hide all telephone numbers from different tables by applying a UDF, and querying the catalog.
For example, your UDF (user defined function) could mutiply the telephone by a given number that you only know. Then, in order to decrypt it, you just have to divide by the same number.
Then, to apply this procedure to all tables, you have to query the catalog. For example,
select tabschema, tabname
from syscat.columns
where colname like 'PHONE%'
Once, you are sure of the tables, you could update them with your UDF
select 'update ' || trim(tabschema) || '.' || trim(tabname) || ' set ' || trim(colname) || ' = myUDF(' || colname || ', 5) ;' from syscat.columns where colname like 'PHONE%'
Let's say 5 is your encryption number.
You just have to execute the output in order to hide the telephones.

Related

How to join tables in two Firebird databases?

Currently I'm working on a simple library project using Embarcadero C++Builder 10.3 Community Edition, and Firebird and FlameRobin to create databases.
So far, I need only use simple queries, that were connected to a single database. Therefore, I used TFDConnection and TFDPhysFbDriverLink to connect to a .fdb file. Then, TFDQuery to create SQL commands and TDataSource. It works great.
Unfortunately, now I must join two tables. How do I write this command? I tried this:
SELECT * FROM users_books
join books on
users_books.id_book = books.id
where users_books and books are databases.
I got an error:
SQL error code = -204
Table unknown
BOOKS.
So I think I must connect somehow to these two databases simultaneously. How to do that?
Firebird databases are isolated and don't know about other databases. As a result, it is not possible to join tables across databases with a normal select statement.
What you can do, is use PSQL (Procedural SQL), for example in an EXECUTE BLOCK. You can then use FOR EXECUTE STATEMENT ... ON EXTERNAL to loop over the table in the other database, and then 'manually' join the local table using FOR SELECT (or vice versa).
For example (assuming a table user_books in the remote database, and a table books in the current database):
execute block
returns (book_id integer, book_title varchar(100), username varchar(50))
as
begin
for execute statement 'select book_id, username from user_books'
on external 'users_books' /* may need AS USER and PASSWORD clause as well */
into book_id, username do
begin
for select book_title from books where id = :book_id
into book_title do
begin
suspend;
end
end
end

How to copy the sequence numbers in postgresql

For a postgres based database I need to mirror the table definitions and sequence numbers from one schema to another. For the purpose of copying the schema definitions, I've been able to use pg_dump with schema definition only, however documentation seems to indicate that sequence numbers are only exported when data export is selected.
Is there an easy to export the corresponding sequence numbers in the schema exportation or an easy way to transfer these values or is the only alternative to interface with the database from a scripting language?
Looking at the dump the pg_dump first writes the creation of the sequence and the corrects that start value with
SELECT pg_catalog.setval('tuutti_id_seq', 4, true);
So if you do a schema-only dump you can construct the statement from information schema, for example with SQL query:
SELECT 'SELECT pg_catalog.setval(''' || sequence_name || ''', ' || start_value || ', true);'
FROM information_schema.sequences;

How do I grant select for a user on all tables?

I have a user in my DB2 database that I want to grant select rights on all tables and views for a given schema. Any thoughts on how to do that as one SQL statement?
In order to grant select to a given user, you have to "generate" the sentence for each table and view of a given schema. You can do it via the CLP with a query like this:
db2 -x "select 'grant select on table ' || rtrim(tabschema) || '.' || rtrim(tabname) || ' to user JOHN_DOE' from syscat.tables where tabschema like 'FOO%' and (type = 'T' or type = 'V')" | db2 +p -tv
This command line will generate the grants for user JOHN_DOE for all tables (T) and views (V) of any schema starting with FOO.
If you have many tables, the output will be very big and the internal buffer will be filled. Reissue the command by generating the grants for a smaller set of tables.
If you are not sure about what you are going to execute, issue the previous command without the final part (| db2 +p -tv), this will write the commands in the standard output. However, this part is the most important, because this executes the generated output.
For more details, please check the InfoCenter or my blog http://angocadb2.blogspot.com/2011/12/ejecutar-la-salida-de-un-query-en-clp.html (In Spanish)

SQL Server openrowset() test column count in MS Access table

Haven't found an answer via Google. I need to execute this code from SQL Server stored proc.
I have a folder with 100+ access dbs with a table called tblReports. Some of the access db's have an extra column in tblReports called AdminReport.
I need to capture the extra column if it exists, thus... I need to test how many columns are in tblReports so that I can use an if/else statement in the sp to generate the correct sql based on the column count.
I'd love to read your thoughts, here's the relevant snippet.
set #sql = 'Insert into CustomerServiceIntranet.dbo.ReportCriteria
(UserInfo,RptNbr,RptType,RptDesc,GroupCDBrk,ClientCDBrk,CategoryCDBrk,
UserIDBrk,UnitCDBrk,WrkTypeBrk,StatCDBrk,StatDatBrk,
ExperBrk,GroupList,ClientList,CategoryList,UserIDList,BusAreaList,
WrkTypList,StatusList,QueueList,ReviewDay,ReviewDayNA,
ErrorImpact,DateRange,DataSource,RptPathFile)'
+ 'Select '''+ #userfilename + ''', ors.* '
+ 'from (select * From Openrowset(''Microsoft.ACE.OLEDB.12.0'','''
+ #CurrentName
+ ''';''Admin'';,''select * from tblReports'')) ors'
The standard approach would be to link to tblReports by calling DoCmd.TransferDatabase. You would then be able to count number of the fields in the table, before embarking on any SQL. At the end of the look you would delete the link by calling DoCmd.DeleteObject.
It certainly looks neater than what you are trying to do.

SQL join from multiple tables

We've got a system (MS SQL 2008 R2-based) that has a number of "input" database and a one "output" database. I'd like to write a query that will read from the output DB, and JOIN it to data in one of the source DB. However, the source table may be one or more individual tables :( The name of the source DB is included in the output DB; ideally, I'd like to do something like the following (pseudo-SQL ahoy)
select o.[UID]
,o.[description]
,i.[data]
from [output].dbo.[description] as o
left join (select [UID]
,[data]
from
[output.sourcedb].dbo.datatable
) as i
on i.[UID] = o.[UID];
Is there any way to do something like the above - "dynamically" specify the database and table to be joined on for each row in the query?
Try using the exec function, then specify the select as a string, adding variables for database names and tables where appropriate. Simple example:
DECLARE #dbName VARCHAR(255), #tableName VARCHAR(255), #colName VARCHAR(255)
...
EXEC('SELECT * FROM ' + #dbName + '.dbo.' + #tableName + ' WHERE ' + #colName + ' = 1')
No, the table must be known at the time you prepare the query. Otherwise how would the query optimizer know what indexes it might be able to use? Or if the table you reference even has an UID column?
You'll have to do this in stages:
Fetch the sourcedb value from your output database in one query.
Build an SQL query string, interpolating the value you fetched in the first query into the FROM clause of the second query.
Be careful to check that this value contains a legitimate database name. For instance, filter out non-alpha characters or apply a regular expression or look it up in a whitelist. Otherwise you're exposing yourself to a SQL Injection risk.
Execute the new SQL string you built with exec() as #user353852 suggests.