785.TXT ===================================================================== SEARCH AND REPLACE ===================================================================== PRODUCT: R:BASE VERSION: 4.5+ or Higher ===================================================================== CATALOG: Programming in R:BASE AREA : Logic & Data Manipulation ===================================================================== R:BASE 4.5 Plus! added a new SuperMath function, SRPL, to do string search and replace. This function lets you search for and replace just part of a field; you no longer need to replace an entire TEXT or NOTE field. The following program demonstrates the use of the SRPL function. In addition to using the SRPL function, the program queries system tables to present only TEXT or NOTE columns for selection. It prompts the user for the old string and for the replacement string. The user can then opt to change all rows that contain the old string, or choose to verify each change. The program builds an UPDATE command, which is then executed as an ampersand variable to change all rows. For more information about using ampersand variables, see "Working With Variables" in the Sept/Oct 1993 Exchange, Fax doc #738. A DECLARE CURSOR is used to verify each change. For more information about DECLARE CURSOR, see "Using Cursors" in this issue of the Exchange. *(SEARCH.CMD - Search and replace program) CLS CLEAR ALL VAR SET ERROR VAR VsEvar SET MESSAGES OFF SET ERROR MESSAGES OFF CLS LABEL toploop CLS FROM 3,42 TO 7,78 BLACK CLS FROM 2,40 TO 6,77 CYAN WRITE ' RB:Search' AT 3,52 YELLOW ON CYAN WRITE ' Text Search and Replace Program.' + AT 5,42 YELLOW ON CYAN CHOOSE VsTblview FROM #TBLVIEWS AT 5 12 IF VsEvar <> 0 THEN PAUSE 2 USING 'No tables or views available.' GOTO alldone ENDIF IF VsTblview = '[Esc]' THEN GOTO alldone ENDIF SET VAR VsTabid = sys_table_id FROM sys_tables + WHERE sys_table_name = .VsTblview SELECT COUNT(*) INTO VsEdiCols FROM sys_columns + WHERE sys_table_id = .VsTabid AND + (sys_data_type = 3 OR sys_data_type = 8) IF VsEdiCols = 0 THEN PAUSE 2 USING + 'This table has no Text or Note columns to modify.' + AT CENTER,CENTER DEFAULT GOTO toploop ENDIF CHOOSE VsColumn FROM #VALUES FOR sys_column_name + FROM sys_columns WHERE sys_table_id = .VsTabid AND + (sys_data_type = 3 OR sys_data_type = 8) CASCADE IF VsColumn = '[Esc]' THEN GOTO toploop ENDIF SET VAR VsColLen INT = sys_length FROM sys_columns + WHERE sys_column_name = .VsColumn IF VsColLen > 40 THEN SET VAR VsColLen = 40 ENDIF CLS FROM 10 12 TO 18 72 BLACK CLS FROM 9 10 TO 17 71 GREEN SET VAR VsOldString TEXT, VsNewString TEXT WRITE 'Enter the old text string to search for.' + AT 10 14 BLACK ON GREEN FILLIN VsOldString = .VsColLen AT 11 14 YELLOW ON GREEN IF VsOldString IS NULL THEN GOTO toploop ENDIF WRITE 'Enter the new replacement string.' + AT 12 14 BLACK ON GREEN FILLIN VsNewString = .VsColLen AT 13 14 YELLOW ON GREEN IF VsNewString IS NULL THEN GOTO toploop ENDIF SNAP search.$$$ FROM 1,1 TO 25,80 SELECT COUNT(*) INTO VsNumRows FROM &VsTblview + WHERE &VsColumn CONTAINS .VsOldString IF VsNumRows = 0 THEN PAUSE 2 USING 'No matching rows found.' + AT CENTER,CENTER DEFAULT GOTO toploop ENDIF WRITE 'ALL rows containing the old string + will be replaced.' AT 15 14 RED ON GREEN WRITE .VsNumRows, 'rows will be updated.' + AT 16 24 RED ON GREEN DIALOG 'Confirm each change?' + VsConfirm, VsKey YES AT 19 IF VsConfirm = 'NO' THEN DIALOG 'Continue with update of all rows?' + VsOk VsEnd YES AT 19 IF VsOk = 'NO' THEN GOTO alldone ELSE SET VAR VsUpdate = + ('UPDATE' & .VsTblview & 'SET' & .VsColumn + + '=' + '(SRPL(' + .VsColumn + ',' + '''' + + .VsOldString + '''' + ',' + '''' + .VsNewString + + '''' + ',0))' & 'WHERE' & .VsColumn & + 'LIKE' & + '''%' + .VsOldString + '%''') &VsUpdate CLS FROM 15 12 TO 17 68 GREEN IF VsEvar = 0 THEN WRITE 'Update successful,' .VsNumRows, + 'rows updated.' AT 16 14 RED ON GREEN PAUSE 2 ELSE WRITE 'Update did not complete.' + AT 16 14 RED ON GREEN PAUSE 2 ENDIF ENDIF ELSE SET VAR VsErrCnt INT = 0, VsUpdCnt INT = 0, + VsOld TEXT, VsNew TEXT SET VAR VsWhereString = ('%'+.VsOldString+'%') DROP CURSOR c1 DECLARE c1 CURSOR FOR SELECT &VsColumn + FROM &VsTblview + WHERE &VsColumn LIKE .VsWhereString OPEN c1 FETCH c1 INTO VsOld VsInd1 WHILE SQLCODE <> 100 THEN SET VAR VsNew = + (SRPL(.VsOld,.VsOldString,.VsNewString,0)) CLS FROM 16 9 TO 19 73 BLACK CLS FROM 15 8 TO 18 72 CYAN WRITE 'Old row value: ', .VsOld AT 16 10 + BLACK ON CYAN WRITE 'New row value: ', .VsNew AT 17 10 + RED ON CYAN DIALOG 'Change this row?' VsOk VsEnd YES AT 19 IF VsOk = 'yes' THEN UPDATE &VsTblview SET &VsColumn = .VsNew + WHERE CURRENT OF c1 IF VsEvar <> 0 THEN SET VAR VsErrCnt = -1 ELSE SET VAR VsUpdCnt = (.VsUpdCnt + 1) ENDIF ENDIF FETCH c1 INTO VsOld VsInd1 ENDWHILE DROP CURSOR c1 DISPLAY search.$$$ AT 1 IF VsErrCnt >= 0 THEN SET VAR VsMsg = + ( 'Update successful,' & CTXT(.VsUpdCnt) & + 'rows updated.' ) PAUSE 2 USING .VsMsg AT 16 DEFAULT ELSE PAUSE 2 USING 'Update did not complete.' + AT 16 DEFAULT ENDIF ENDIF CLS *(reset) LABEL alldone CLEAR VAR Vs% SET ERROR VAR OFF CLS SET MESSAGES ON SET ERROR MESSAGES ON RETURN display information screen select a table or view Retrieve the table id number from the system table, SYS_TABLES. The table id number is used to retrieve the columns. A listing of all system tables and columns is located in Appendix D of the Startup & New Features Guide Make sure there are TEXT or NOTE columns in the selected table. The system table, SYS_COLUMNS, is queried using the table id - a TEXT column has a datatype number of 3 a NOTE column has a datatype number of 8 The system table, SYS_COLUMNS, is queried using the table id. A menu of TEXT and NOTE columns from the selected table is displayed. Select a column from the menu Find the length of the selected column by querying the system table SYS_COLUMNS. If the column length is more than 40, the text entered is limited to 40. It is limited for display purposes, i.e. to fit in the designated display area on the screen. To let users enter longer values, one option is to use a FILLIN box. Refer to the Command Dictionary for information on using a FILLIN box Prompt for the old and new values If no string is entered the program aborts and returns to the select a table menu Take a snapshot of the screen for displaying messages when the update is complete Find out how many rows meet the condition. If no matching rows are found, return to the tables menu If yes to confirm each change, a DECLARE CURSOR is used to step through each matching row. If no, an UPDATE command is built to change all rows Let the user abort the operation Build the UPDATE command. The keywords of the UPDATE command are combined with the user selected values. The four quotes together tell R:BASE to put a single quote in the result. The LIKE operator is used so that if the selected column is indexed, the index will be used in the WHERE clause to make the search faster. The resulting variable value looks like this: Variable = Value Type -------- ---------------------------- ----- VsUpdate = UPDATE employee SET TEXT empaddress=(SRPL(empaddress,'D rive','Dr.',0)) WHERE empaddress LIKE '%Drive%' Notice that the contents of the variable look just like the UPDATE command as you would enter it at the R> prompt. Execute the UPDATE command Set up the WHERE clause for the DECLARE CURSOR to do row by row updates Define a cursor to point to all the matching rows Display the old and new values and prompt to confirm the change Execute an UPDATE command to change the row the cursor is currently pointing at The two count variables indicate if the update failed on any row All variables in this command file start with Vs to make it easy to clear them when done