|
| 1 | +function Find-DbaObject { |
| 2 | + <# |
| 3 | + .SYNOPSIS |
| 4 | + Searches database objects by name or column name across SQL Server databases using regex patterns. |
| 5 | +
|
| 6 | + .DESCRIPTION |
| 7 | + Provides a unified search across all database object types (tables, views, stored procedures, functions, |
| 8 | + synonyms, triggers) by matching their names against a regex pattern. Optionally extends the search to |
| 9 | + column names within tables and views. This complements the existing Find-DbaStoredProcedure, Find-DbaView, |
| 10 | + and Find-DbaTrigger commands which search object definition text rather than object or column names. |
| 11 | +
|
| 12 | + Uses T-SQL queries against sys.objects and sys.columns for optimal performance. Pattern matching is |
| 13 | + performed in PowerShell using full regex syntax. |
| 14 | +
|
| 15 | + .PARAMETER SqlInstance |
| 16 | + The target SQL Server instance or instances. This can be a collection and receive pipeline input. |
| 17 | +
|
| 18 | + .PARAMETER SqlCredential |
| 19 | + Login to the target instance using alternative credentials. Accepts PowerShell credentials (Get-Credential). |
| 20 | +
|
| 21 | + Windows Authentication, SQL Server Authentication, Active Directory - Password, and Active Directory - |
| 22 | + Integrated are all supported. |
| 23 | +
|
| 24 | + For MFA support, please use Connect-DbaInstance. |
| 25 | +
|
| 26 | + .PARAMETER Database |
| 27 | + Specifies one or more databases to search. When omitted, searches all user databases on the instance. |
| 28 | + Use this to focus searches on specific databases when you know where the objects are located. |
| 29 | +
|
| 30 | + .PARAMETER ExcludeDatabase |
| 31 | + Specifies databases to skip during the search. Accepts multiple database names. |
| 32 | + Use this to exclude large databases or test environments from the search. |
| 33 | +
|
| 34 | + .PARAMETER Pattern |
| 35 | + The regular expression pattern to match against object names (and optionally column names). |
| 36 | + Supports full regex syntax for complex pattern matching. For example, use "^Customer" to find objects |
| 37 | + starting with "Customer", or "Service|Product" to find objects mentioning either term. |
| 38 | +
|
| 39 | + .PARAMETER ObjectType |
| 40 | + Filters the search to specific object types. Accepts one or more of: |
| 41 | + - Table: User tables (sys.objects type U) |
| 42 | + - View: Views (sys.objects type V) |
| 43 | + - StoredProcedure: Stored procedures (sys.objects type P) |
| 44 | + - ScalarFunction: Scalar-valued functions (sys.objects type FN) |
| 45 | + - TableValuedFunction: Inline and multi-statement table-valued functions (sys.objects type IF/TF) |
| 46 | + - Synonym: Synonyms (sys.objects type SN) |
| 47 | + - Trigger: SQL triggers (sys.objects type TR) |
| 48 | + - All: All of the above (default) |
| 49 | +
|
| 50 | + .PARAMETER IncludeColumns |
| 51 | + When specified, additionally searches column names within tables and views for the given pattern. |
| 52 | + Results with column name matches include a MatchType of "ColumnName" and the matching column name. |
| 53 | + This is useful for finding which tables or views contain a column related to a specific domain concept. |
| 54 | +
|
| 55 | + .PARAMETER IncludeSystemObjects |
| 56 | + Includes system objects (those shipped with SQL Server) in the search results. |
| 57 | + By default, only user-created objects are searched. |
| 58 | +
|
| 59 | + .PARAMETER IncludeSystemDatabases |
| 60 | + Includes system databases (master, model, msdb, tempdb) in the search scope. |
| 61 | + By default, only user databases are searched. |
| 62 | +
|
| 63 | + .PARAMETER EnableException |
| 64 | + By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message. |
| 65 | + This avoids overwhelming you with "sea of red" exceptions, but is inconvenient because it basically disables advanced scripting. |
| 66 | + Using this switch turns this "nice by default" feature off and enables you to catch exceptions with your own try/catch. |
| 67 | +
|
| 68 | + .NOTES |
| 69 | + Tags: Object, Lookup, Find |
| 70 | + Author: the dbatools team + Claude |
| 71 | +
|
| 72 | + Website: https://dbatools.io |
| 73 | + Copyright: (c) 2018 by dbatools, licensed under MIT |
| 74 | + License: MIT https://opensource.org/licenses/MIT |
| 75 | +
|
| 76 | + .LINK |
| 77 | + https://dbatools.io/Find-DbaObject |
| 78 | +
|
| 79 | + .OUTPUTS |
| 80 | + PSCustomObject |
| 81 | +
|
| 82 | + Returns one object per match found. When -IncludeColumns is used, there may be multiple results |
| 83 | + per database object (one for the object name match plus one per matching column name). |
| 84 | +
|
| 85 | + Properties: |
| 86 | + - ComputerName: The computer name of the SQL Server instance |
| 87 | + - SqlInstance: The SQL Server instance name |
| 88 | + - Database: The database containing the matched object |
| 89 | + - Schema: The schema of the matched object |
| 90 | + - Name: The name of the matched object |
| 91 | + - ObjectType: The SQL Server type description (e.g., USER_TABLE, VIEW, SQL_STORED_PROCEDURE) |
| 92 | + - MatchType: "ObjectName" when the object name matched, "ColumnName" when a column name matched |
| 93 | + - ColumnName: The matching column name when MatchType is "ColumnName", otherwise null |
| 94 | + - CreateDate: DateTime when the object was created |
| 95 | + - LastModified: DateTime when the object was last modified |
| 96 | +
|
| 97 | + .EXAMPLE |
| 98 | + PS C:\> Find-DbaObject -SqlInstance DEV01 -Pattern Service |
| 99 | +
|
| 100 | + Searches all user databases on DEV01 for any object whose name contains "Service". |
| 101 | +
|
| 102 | + .EXAMPLE |
| 103 | + PS C:\> Find-DbaObject -SqlInstance DEV01 -Pattern Service -IncludeColumns |
| 104 | +
|
| 105 | + Searches all user databases on DEV01 for objects named with "Service" and tables/views |
| 106 | + that have columns whose names contain "Service". |
| 107 | +
|
| 108 | + .EXAMPLE |
| 109 | + PS C:\> Find-DbaObject -SqlInstance DEV01 -Pattern "^Customer" -ObjectType Table |
| 110 | +
|
| 111 | + Finds all user tables on DEV01 whose names start with "Customer". |
| 112 | +
|
| 113 | + .EXAMPLE |
| 114 | + PS C:\> Find-DbaObject -SqlInstance DEV01 -Pattern "Invoice" -Database Accounting -IncludeColumns |
| 115 | +
|
| 116 | + Searches the Accounting database for objects and columns related to "Invoice". |
| 117 | +
|
| 118 | + .EXAMPLE |
| 119 | + PS C:\> Find-DbaObject -SqlInstance sql2019 -Pattern "Service|Product" -ObjectType Table, View |
| 120 | +
|
| 121 | + Finds all tables and views whose names contain either "Service" or "Product". |
| 122 | +
|
| 123 | + #> |
| 124 | + [CmdletBinding()] |
| 125 | + param ( |
| 126 | + [parameter(Mandatory, ValueFromPipeline)] |
| 127 | + [DbaInstanceParameter[]]$SqlInstance, |
| 128 | + [PSCredential]$SqlCredential, |
| 129 | + [object[]]$Database, |
| 130 | + [object[]]$ExcludeDatabase, |
| 131 | + [parameter(Mandatory)] |
| 132 | + [string]$Pattern, |
| 133 | + [ValidateSet("Table", "View", "StoredProcedure", "ScalarFunction", "TableValuedFunction", "Synonym", "Trigger", "All")] |
| 134 | + [string[]]$ObjectType = @("All"), |
| 135 | + [switch]$IncludeColumns, |
| 136 | + [switch]$IncludeSystemObjects, |
| 137 | + [switch]$IncludeSystemDatabases, |
| 138 | + [switch]$EnableException |
| 139 | + ) |
| 140 | + |
| 141 | + begin { |
| 142 | + $typeCodeMap = @{ |
| 143 | + "Table" = @("'U'") |
| 144 | + "View" = @("'V'") |
| 145 | + "StoredProcedure" = @("'P'") |
| 146 | + "ScalarFunction" = @("'FN'") |
| 147 | + "TableValuedFunction" = @("'IF'", "'TF'") |
| 148 | + "Synonym" = @("'SN'") |
| 149 | + "Trigger" = @("'TR'") |
| 150 | + } |
| 151 | + |
| 152 | + if ("All" -in $ObjectType) { |
| 153 | + $typeFilter = "'U', 'V', 'P', 'FN', 'IF', 'TF', 'SN', 'TR'" |
| 154 | + } else { |
| 155 | + $typeCodes = @() |
| 156 | + foreach ($type in $ObjectType) { |
| 157 | + $typeCodes += $typeCodeMap[$type] |
| 158 | + } |
| 159 | + $typeFilter = ($typeCodes | Select-Object -Unique) -join ", " |
| 160 | + } |
| 161 | + |
| 162 | + $sysFilter = if ($IncludeSystemObjects) { "" } else { "AND o.is_ms_shipped = 0" } |
| 163 | + |
| 164 | + $sqlObjects = " |
| 165 | + SELECT |
| 166 | + OBJECT_SCHEMA_NAME(o.object_id) AS SchemaName, |
| 167 | + o.name AS ObjectName, |
| 168 | + RTRIM(o.type) AS ObjectTypeCode, |
| 169 | + o.type_desc AS ObjectType, |
| 170 | + o.create_date AS CreateDate, |
| 171 | + o.modify_date AS LastModified |
| 172 | + FROM sys.objects o |
| 173 | + WHERE o.type IN ($typeFilter) |
| 174 | + $sysFilter" |
| 175 | + |
| 176 | + $sqlColumns = " |
| 177 | + SELECT |
| 178 | + OBJECT_SCHEMA_NAME(c.object_id) AS SchemaName, |
| 179 | + OBJECT_NAME(c.object_id) AS ObjectName, |
| 180 | + RTRIM(o.type) AS ObjectTypeCode, |
| 181 | + o.type_desc AS ObjectType, |
| 182 | + o.create_date AS CreateDate, |
| 183 | + o.modify_date AS LastModified, |
| 184 | + c.name AS ColumnName |
| 185 | + FROM sys.columns c |
| 186 | + INNER JOIN sys.objects o ON c.object_id = o.object_id |
| 187 | + WHERE o.type IN ($typeFilter) |
| 188 | + $sysFilter" |
| 189 | + } |
| 190 | + |
| 191 | + process { |
| 192 | + foreach ($instance in $SqlInstance) { |
| 193 | + try { |
| 194 | + $server = Connect-DbaInstance -SqlInstance $instance -SqlCredential $SqlCredential |
| 195 | + } catch { |
| 196 | + Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $instance -Continue |
| 197 | + } |
| 198 | + |
| 199 | + if ($server.versionMajor -lt 9) { |
| 200 | + Write-Message -Level Warning -Message "This command only supports SQL Server 2005 and above." |
| 201 | + Continue |
| 202 | + } |
| 203 | + |
| 204 | + if ($IncludeSystemDatabases) { |
| 205 | + $dbs = $server.Databases | Where-Object { $_.Status -eq "normal" } |
| 206 | + } else { |
| 207 | + $dbs = $server.Databases | Where-Object { $_.Status -eq "normal" -and $_.IsSystemObject -eq $false } |
| 208 | + } |
| 209 | + |
| 210 | + if ($Database) { |
| 211 | + $dbs = $dbs | Where-Object Name -In $Database |
| 212 | + } |
| 213 | + |
| 214 | + if ($ExcludeDatabase) { |
| 215 | + $dbs = $dbs | Where-Object Name -NotIn $ExcludeDatabase |
| 216 | + } |
| 217 | + |
| 218 | + foreach ($db in $dbs) { |
| 219 | + Write-Message -Level Verbose -Message "Searching object names in database $db on $instance" |
| 220 | + |
| 221 | + Write-Message -Level Debug -Message $sqlObjects |
| 222 | + $objectRows = $db.ExecuteWithResults($sqlObjects).Tables.Rows |
| 223 | + |
| 224 | + foreach ($row in $objectRows) { |
| 225 | + if ($row.ObjectName -match $Pattern) { |
| 226 | + [PSCustomObject]@{ |
| 227 | + ComputerName = $server.ComputerName |
| 228 | + SqlInstance = $server.ServiceName |
| 229 | + Database = $db.Name |
| 230 | + Schema = $row.SchemaName |
| 231 | + Name = $row.ObjectName |
| 232 | + ObjectType = $row.ObjectType |
| 233 | + MatchType = "ObjectName" |
| 234 | + ColumnName = $null |
| 235 | + CreateDate = $row.CreateDate |
| 236 | + LastModified = $row.LastModified |
| 237 | + } |
| 238 | + } |
| 239 | + } |
| 240 | + |
| 241 | + if ($IncludeColumns) { |
| 242 | + Write-Message -Level Verbose -Message "Searching column names in database $db on $instance" |
| 243 | + |
| 244 | + Write-Message -Level Debug -Message $sqlColumns |
| 245 | + $columnRows = $db.ExecuteWithResults($sqlColumns).Tables.Rows |
| 246 | + |
| 247 | + foreach ($row in $columnRows) { |
| 248 | + if ($row.ColumnName -match $Pattern) { |
| 249 | + [PSCustomObject]@{ |
| 250 | + ComputerName = $server.ComputerName |
| 251 | + SqlInstance = $server.ServiceName |
| 252 | + Database = $db.Name |
| 253 | + Schema = $row.SchemaName |
| 254 | + Name = $row.ObjectName |
| 255 | + ObjectType = $row.ObjectType |
| 256 | + MatchType = "ColumnName" |
| 257 | + ColumnName = $row.ColumnName |
| 258 | + CreateDate = $row.CreateDate |
| 259 | + LastModified = $row.LastModified |
| 260 | + } |
| 261 | + } |
| 262 | + } |
| 263 | + } |
| 264 | + } |
| 265 | + } |
| 266 | + } |
| 267 | +} |
0 commit comments