Skip to content

Commit db77a34

Browse files
Find-DbaObject - Add unified command to search database objects by name (#10321)
1 parent 0c486b9 commit db77a34

4 files changed

Lines changed: 535 additions & 0 deletions

File tree

dbatools.psd1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@
172172
'Find-DbaDbUnusedIndex',
173173
'Find-DbaInstance',
174174
'Find-DbaLoginInGroup',
175+
'Find-DbaObject',
175176
'Find-DbaOrphanedFile',
176177
'Find-DbaSimilarTable',
177178
'Find-DbaStoredProcedure',

dbatools.psm1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,7 @@ if ($PSVersionTable.PSVersion.Major -lt 5) {
500500
'Export-DbaXESession',
501501
'Test-DbaOptimizeForAdHoc',
502502
'Find-DbaStoredProcedure',
503+
'Find-DbaObject',
503504
'Measure-DbaBackupThroughput',
504505
'Get-DbaDatabase',
505506
'Find-DbaUserObject',

public/Find-DbaObject.ps1

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
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

Comments
 (0)