简体   繁体   中英

Looking for specific solution for C# Regex pattern SQL Table

I am modifying a C# app to loop through a bunch of SQL files and replacing a view name with its corresponding table name.

For example, a view named "Item" should be replaced with a table named "Item_mst".

I have a mapping file that the app looks at to determine which tables to replace and looks like this:

VIEWNAME1,TABLENAME1_MST
VIEWNAME2,TABLENAME2_MST

The problem is, there are a lot of scenarios to look for, I have described them below with an example SQL file.

Select 
    i.item <<Matches the Item table but is actually the name of the column, no replace
    ,dbo.item.u_m <<Matches the Item table with DBO., replace
    ,lot <<Matches the lot table but is actually the name of a column, no replace
    ,(Select top 1 cost from itemcost) as Cost <<itemcost is a table, replace
    ,(Select top 1 cost2 from dbo.itemcost) as Cost2 <<matches the itemcost table with dbo., replace
From 
    dbo.item i <<matches the item table with dbo.,replace
    cross join itemlot <<matches the itemlot table, replace

As you can see, there are many different scenarios, and I am having a hard time writing a regex/find and replace algorithm to catch every scenario reliably.

I am matching dbo.tablename and replacing those easy enough, it is the remaining scenarios I am having troubles with. Are there any REGEX experts out there that have any ideas?

Here is a code snippet:

//Replace all matched views with table names
for (int j = 0; j < viewCount.Count(); j++)
{
    //replace for "."
    curFileText = curFileText.Replace(".", "XXXPERIODXXX");
    curFileText = Regex.Replace(curFileText, "dboXXXPERIODXXX" + ViewTables[0, j] + "XXXPERIODXXX", "dboXXXPERIODXXX" + ViewTables[1, j] + "XXXPERIODXXX", RegexOptions.IgnoreCase);
    curFileText = curFileText.Replace("XXXPERIODXXX", ".");

    //replace for "newline"
    curFileText = curFileText.Replace(System.Environment.NewLine, "XXXNEWLINEXXX");
    curFileText = Regex.Replace(curFileText, ViewTables[0, j] + "XXXNEWLINEXXX", ViewTables[1, j] + "XXXNEWLINEXXX", RegexOptions.IgnoreCase);
    curFileText = curFileText.Replace("XXXNEWLINEXXX", System.Environment.NewLine);

    //Fix .column_mst spots
    curFileText = curFileText.Replace("dbo.", "XXXDBODOTXXX");
    curFileText = curFileText.Replace(".", "XXXDOTXXX");
    curFileText = Regex.Replace(curFileText, "XXXDOTXXX" + ViewTables[1, j], "XXXDOTXXX" + ViewTables[0, j], RegexOptions.IgnoreCase);
    curFileText = curFileText.Replace("XXXDOTXXX", ".");
    curFileText = curFileText.Replace("XXXDBODOTXXX", "dbo.");

    //replace for " "
    curFileText = curFileText.Replace(" ", "XXXSPACEXXX");
    curFileText = Regex.Replace(curFileText, "dbo." + ViewTables[0, j] + "XXXSPACEXXX", "dbo." + ViewTables[1, j] + "XXXSPACEXXX", RegexOptions.IgnoreCase);
    curFileText = curFileText.Replace("XXXSPACEXXX", " ");
}

Why not tackle the problem backwards? Depending on your RDBMS, you can use a query like select table_name, view_definition from information_schema.views to get a list of all view names and underlying SQL. Somewhere in that SQL for each view will be a select ... from <table name> statement for the views that are just based on a single table. Copy those results into Sublime or Notepad++ and use simple regex (replace ([\\w\\W]+)(\\s+from\\s+)(\\S+)([\\w\\W]+) with $3 ) to derive a list of view names associated with their underlying tables like this:
vSomeView SomeTable vOtherView OtherTable

Once you have that, use regular expressions again to generate a .Replace chain to replace ^([^ ])( )(\\w\\W)$ with .Replace("$1", "$3") . Copy/paste that .Replace chain into the C# code you're using to perform this migration.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM