Hi I am struggling into writing a PowerShell script to drop the database, based on some conditions.I have SQL script running but facing too many syntax error when converting same script to PowerShell
DECLARE #Sql as NVARCHAR(MAX) = (SELECT 'DROP DATABASE ['+ name + ']; ' FROM sys.databases WHERE name like '%Dev%'
and database_id < (SELECT max(database_id) FROM sys.databases where source_database_id IS NOT NULL and name like '%Dev%' )
FOR XML PATH('')) EXEC sys.sp_executesql #Sql
I am new to PowerShell script so any help would be great.
I tried something like below but getting a syntax error in PowerShell
$query= 'DECLARE #Sql as NVARCHAR(MAX) = (SELECT 'DROP DATABASE ['+ name + ']; ' FROM sys.databases WHERE name like '%Dev%'
and database_id < (SELECT max(database_id) FROM sys.databases where source_database_id IS NOT NULL and name like '%Dev%' )
FOR XML PATH('')) EXEC sys.sp_executesql #Sql '
echo $query
Invoke-Sqlcmd -ServerInstance ''XXXX' -Username 'XX' -Password 'XXXXX' -Query $query -QueryTimeout 600 -Verbose
I Just putted everything in "" and it worked.
Related
I am trying to extract list of user defined assemblies through PowerShell for one of SQL Server administration for automation.
When I open SSMS and execute this query as
Select name, permission_set_desc
From sys.assemblies
I am able to get the output as 2 rows as below
Name
Permission_Set_Desc
Microsoft.SqlServer.Types
UNSAFE_ACCESS
StairwayToSQLCLR-02-Example
SAFE_ACCESS
When I execute the same T-SQL through PowerShell using Invoke-SQLCMD command, I do not get any user defined assemblies rather only system defined assembly.
This is the command I used in PowerShell:
$query = "Select name, permission_Set_Desc from sys.assemblies"
Invoke-Sqlcmd -Query $query -AbortOnError -OutputSQLErrors $true
I get the below only which is system defined assembly.
Name
Permission_Set_Desc
Microsoft.SqlServer.Types
UNSAFE_ACCESS
I am unable to get the user defined assemblies from PowerShell.
Did I miss something here?
As #Vijayanand A said, assemblies are defined at database level. However, you can iterate all databases and display all of them with attached assemblies:
DECLARE #sql nvarchar(MAX) = '';
SELECT #sql += 'SELECT '+
QUOTENAME(DB.Name, '''') + ' COLLATE database_default db, '+
'name COLLATE database_default name, '+
'permission_set_desc COLLATE database_default permission_set_desc '+
'FROM ' + QUOTENAME(DB.Name) + '.sys.assemblies UNION ALL '
FROM sys.databases DB
SET #sql = LEFT(#sql, LEN(#sql)-LEN(' UNION ALL'))
EXEC(#sql)
I have a database in SQL Azure and I am wanting to use a script to drop all the column store indexes.
I am connecting using SSMS using the SQL admin login of the SQL Server.
I am using this script:
declare #sql nvarchar(max);
set #sql = N'';
select #sql = #sql + N'DROP INDEX ' + OBJECT_SCHEMA_NAME(i.OBJECT_ID) + '.' + i.name + N' ON ' + OBJECT_SCHEMA_NAME(i.OBJECT_ID) + '.' + o.name + ';
'
FROM sys.indexes AS i INNER JOIN sys.tables AS o ON i.[object_id] = o.[object_id]
where i.name is not null and o.name is not null and i.type_desc like '%COLUMN%'
PRINT #sql;
EXEC sp_executesql #sql;
An example statement:
DROP INDEX [dbo].[CCI_MyTable] ON [dbo].[MyTable];
When run, this generates error:
Incorrect syntax near the keyword 'ON'.
If I try just:
DROP INDEX [dbo].[CCI_MyTable]
This generates error:
Cannot drop the index 'dbo.CCI_MyTable', because it does not exist or you do not have permission.**
In SSMS, I can see the SQL SERVER admin user exists in the [master] database, but does not exist in the DATABASE I am working in.
Within this DATABASE, I am running as 'dbo':
SELECT USER_NAME() -- DBO
SELECT CURRENT_USER; -- DBO
Shouldn't dbo have permissions to drop indexes?
ASK:
What is the proper way to go about this? Do I need to add the admin user to this database? If that user existed, and I connect with SSMS, would user_name() then be that user rather than dbo?
It seems the problem was preceding the index name with the schema (although, I swear many examples I've read do just that).
So the correct script syntax is:
declare #sql nvarchar(max);
set #sql = N'';
select #sql = #sql + N'DROP INDEX ' + i.name + N' ON ' + OBJECT_SCHEMA_NAME(i.OBJECT_ID) + '.' + o.name + ';
'
FROM sys.indexes AS i INNER JOIN sys.tables AS o ON i.[object_id] = o.[object_id]
where i.name is not null and o.name is not null and i.type_desc like '%COLUMN%'
PRINT #sql;
EXEC sp_executesql #sql;
Is there any way to reference the table inside a 'sp_MSforeachtable' loop running inside a 'sp_msforeachdb' loop?
For example, in the following query the '?' is always referencing the database:
DECLARE #cmd VARCHAR(8000);
SET #cmd = 'USE ?; EXEC sp_MSforeachtable #command1="select db_name = DB_NAME(), db_foreach = ''?'', tb_foreach = ''?'' "'
EXEC sp_msforeachdb #command1 =#cmd
Resulting in:
db_name db_forearch tb_foreach
ServerMonitor master master
I want to have something like:
db_name db_forearch tb_foreach
ServerMonitor master <TABLE_NAME>
What should I change?
Solved. I used my ow cursor, as suggested by Sean. But the #replacechar solution suggested by Ben Thul is exactly what I was looking for.
DECLARE #cmd VARCHAR(8000);
SET #cmd = 'USE ^; EXEC sp_MSforeachtable #command1="select db_name = DB_NAME(), db_foreach = ''^'', tb_foreach = ''?'' "'
EXEC sp_msforeachdb #command1 =#cmd, #replacechar = '^'
Take a look at the parameters for sp_msforeachtable. One of them is #replacechar which, by default, is a question mark (i.e. ?). Feel free to pass in another equally unlikely character to occur in a query (maybe a ^).
Of course, I'd be remiss if I didn't mention that depending on what you're trying to do (and I would argue that anything that you're trying to do over all tables is doable this way), there are easier to read (and write) solutions in powershell:
import-module sqlps -disablenamechecking;
$s = new-object microsoft.sqlserver.management.smo.server '.';
foreach ($db in $s.databases) {
foreach ($table in $db.Tables) {
$table | select parent, name; --merely list the table and database
}
}
For what you are doing you could do something like this. Although this is still using the for each db procedure which can be problematic. You will want to add a where clause to the final select statement to filter out some databases (model, tempdb, master, etc)
declare #TableNames table
(
DatabaseName sysname
, TableName sysname
)
insert #TableNames
EXEC sp_msforeachdb #command1 = 'use ?;select ''?'', name from sys.tables'
select *, 'exec ' + Databasename + '..sp_spaceused [''' + TableName + ']'';'
from #TableNames
I am trying to see a list of tables from Adventureworks DB from "Person" schema in Sql Server 2008. I developed the following SP, but after running it as follows it gives me error "Incorrect syntax near ')'". Do you know how I can revise this SP or exec statement?
CREATE PROCEDURE [getTableNames]
#SchemaName VARCHAR(50)
AS
BEGIN
SET NOCOUNT ON;
SET #SchemaName = 'PERSON'
DECLARE #cmd AS VARCHAR(max)
SET #SchemaName = RTRIM(#SchemaName)
SET #cmd = N'SELECT TABLE_NAME ' +
'FROM information_schema.Tables ' +
'WHERE TABLE_TYPE = ''BASE TABLE'' AND TABLE_SCHEMA = #SchemaName'
END
exec sp_executesql getTableNames, N'#SchemaName NVARCHAR(50), #SchemaName'
You don't actually need to use dynamic SQL here, plus your sproc isn't quite right as you're not executing the #cmd statement. Just use:
CREATE PROCEDURE [getTableNames]
#SchemaName VARCHAR(50)
AS
BEGIN
SET NOCOUNT ON
SELECT TABLE_NAME
FROM information_schema.Tables
WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA = #SchemaName
END
EXECUTE getTableNames 'PERSON'
You don't need dynamic SQL:
select * from sys.tables
where type_desc = 'BASE TABLE' and schema_id = schema_id(#SchemaName)
I'm attempting to use the undocumented system procedure sp_MSforeachtable. But I need to restrict the affected tables to those that start with "smp" and that are in the "dbo" schema. I was able to find how to find procedures that start with "smp". I simply do:
sp_MSforeachtable #command1=' print ''?''', #whereand=' and name like ''smp%'' '
but how do I filter for a given schema using the #whereand parameter?
UPDATE: I tried the following but it didn't work:
sp_MSforeachtable #command1=' print ''?''', #whereand=' and name like ''smp%'' and Left(''?'', 5)=''[dbo]'' '
Update 2: I'm running on SQL Server 2000.
Update for SQL2000:
declare #s nvarchar(1000)
set #s = ' and uid = ' + convert(nvarchar, user_id('my_schema'))
exec sp_msforeachtable #command1='print ''?''', #whereand = #s
This should works in SQL Server 2000 (can't test now):
#whereand = '
AND name like ''smp%'' AND
OBJECTPROPERTY(OBJECT_ID(''name''), ''OwnerID'') = USER_ID(''dbo'')'
Use OBJECTPROPERTY to find the schema owner id.
Edit: OK, tested it on a SQL 2000 box:
#whereand = ' AND name LIKE ''smp%'' AND uid = 1'
OR
#whereand = ' AND name LIKE ''smp%'' AND USER_ID(''dbo'')'
I could not get OBJECTPROPERTY to work
From here:
---------------------
--Drop table of particular shcemaID/shemaName and with name starting with 'Temp_'
Exec sp_MSforeachtable #command1 = "DROP TABLE ? PRINT '? dropped'"
,#whereand = "and uid = (SELECT schema_id FROM sys.schemas WHERE name = 'dbo')
and o.name LIKE 'Temp_%'"
---------------------
This verion works in Sql Server 2005:
exec sp_MSforeachtable
#command1=' print ''?''',
#whereand=' and schema_name(schema_id) = ''dbo'' '
Not exactly sure for Sql Server 2000, but this version might work:
exec sp_MSforeachtable
#command1=' print ''?''',
#whereand=' and user_name(uid) = ''dbo'' '
This worked in 2008 R2
#whereand='and uid = (SELECT schema_id FROM sys.schemas WHERE name = ''dbo'') and o.name LIKE ''TEMP_%'''