Trying to add multiple users on azure SQL - sql-server

declare #Name varchar(100),#sql varchar(400),#sql2 varchar(400),#sql3 varchar(400) ,#sql4 varchar(400) , #psw varchar(10)
--declare #psw varchar(10) = 'Traf#12345'
declare #T table (Name varchar(100))
insert into #T values
('SampleUser1'),
('SampleUser1')
While exists(select * from #T)
begin
select top 1 #Name = name from #T
IF NOT EXISTS (SELECT [name] FROM [sys].[sql_logins] WHERE [name] = #Name)
BEGIN
SET #psw = 'Traf#123'
SET #sql = 'CREATE LOGIN '+'['+#name+']'+' WITH PASSWORD ='+#psw
EXEC (#sql)
END
DELETE FROM #T WHERE Name = #Name
END
output:
Msg 102, Level 15, State 1, Line 1 Incorrect syntax near
'Traf#123'.

Please try the following changes:
declare #Name varchar(100),#sql varchar(400),#sql2 varchar(400),#sql3 varchar(400) ,#sql4 varchar(400)
declare #psw varchar(10) = 'Traf#12345';
declare #T table (Name varchar(100)) ;
insert into #T values
('SampleUser1'),
('SampleUser2')
While exists(select * from #T)
begin
select top 1 #Name = name from #T
IF NOT EXISTS (SELECT [name] FROM [sys].[sql_logins] WHERE [name] = #Name)
BEGIN
SET #sql = 'CREATE LOGIN '+'['+#name+']'+' WITH PASSWORD ='''+ #psw + '''; '
EXEC (#sql)
END
DELETE FROM #T WHERE Name = #Name
END

Related

Have this problem with calling stored procedure unknown object type

I am trying to write a query that needs to call a stored procedure. But it always throws an error:
Unknown object type 'TABLEIXICHistoricalData' used in a CREATE, DROP, or ALTER statement.
This is query:
USE ETLCourse
DECLARE #LOOP TABLE
(
ID INT IDENTITY(1,1),
TableName NVARCHAR(100)
)
INSERT INTO #LOOP (TableName)
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '%_Stocks%'
DECLARE #b INT = 1, #m INT, #t NVARCHAR(100)
SELECT #m = MAX(ID) FROM #LOOP
WHILE #b <= #m
BEGIN
SELECT #t = TableName
FROM #LOOP
WHERE ID = #b
EXECUTE [dbo].[stp_BuildNormalizedTable] #t
SET #b = #b + 1
END
and here is the procedure:
ALTER PROCEDURE [dbo].[stp_BuildNormalizedTable]
#table NVARCHAR(100)
AS
BEGIN
DECLARE #cleanTable NVARCHAR(100),
#s NVARCHAR(MAX)
SET #cleanTable = REPLACE(#table, '_Stocks', 'HistoricalData')
SET #s = 'CREATE TABLE' + #cleanTable + '(ID INT IDENTITY(1,1), Price DECIMAL(13, 4), PriceDate DATE)
INSERT INTO' + #cleanTable + '(Price,PriceDate) SELECT [Adj Close],[Date] FROM'
+ #table + ' ORDER BY Date ASC'
--PRINT #s
EXECUTE sp_executesql #s
END
It should copy two specific column and create a new table by using #Loop table and procedure
You need to add 'space' after 'create table' and 'insert into' and 'from'
declare #s nvarchar(max)
declare #cleantable nvarchar(100)
declare #table nvarchar(100)
set #cleantable = 'aaa'
set #table = 'bbb'
SET #s = 'CREATE TABLE' + #cleanTable + '(ID INT IDENTITY(1,1),Price Decimal(13,4),PriceDate DATE)
Insert into' + #cleanTable
+ '(Price,PriceDate) SELECT [Adj Close],[Date] FROM'
+ #table + ' ORDER BY Date ASC'
print #s
Output:
CREATE TABLEaaa(ID INT IDENTITY(1,1),Price Decimal(13,4),PriceDate DATE)
Insert intoaaa(Price,PriceDate) SELECT [Adj Close],[Date] FROMbbb ORDER BY Date ASC
Use 'print' to check your query.

How to resolve An INSERT EXEC statement cannot be nested in SQL server

I have a sp in which I am returning one single column result. I am trying to store the result into a table type, but I am getting this error:
An INSERT EXEC statement cannot be nested.
I have googled around but didn't find any acceptable solution.
The sp is as follows:-
ALTER PROCEDURE [dbo].[Sp_DemographicFilter_booster]
(
#FilterSelected FilterSelected READONLY,
#CountryCategoryId int=null
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #WhereCondition varchar(500) ;
DECLARE #QueryString Varchar(MAX) ;
DECLARE #QueryString_booster Varchar(MAX) ;
DECLARE #Filter table (FilterColumn Varchar(200),FilterValue Varchar(200))
DECLARE #Result table (SERIAL int)
DECLARE #Result_booster table (SERIAL int)
if( select top 1 FilterColumn FROM #FilterSelected where FilterColumn<>'HISPANIC') is NOT NULL
BEGIN
Insert into #Filter
Select * from #FilterSelected where FilterColumn<>'HISPANIC'
--DECLARE #DemoTbl TABLE (MetricName VARCHAR(100),CatValue VARCHAR(100))
SELECT #WhereCondition= COALESCE( #WhereCondition + ' and ', '')+SubjectList FROM (
SELECT DISTINCT STD.Filtercolumn +' in ('+
ISNULL(STUFF((SELECT ', '+'''' + ssm.Filtervalue+''''
FROM #Filter SSM
INNER JOIN #Filter SUB ON SUB.FilterColumn = SSM.FilterColumn and SUB.FilterColumn=STD.FilterColumn
WHERE sub.FilterValue = ssm.FilterValue
FOR XML PATH('')
), 1, 1, ''), 'Not Assigned Yet')+')' AS SubjectList
FROM #Filter STD)A
print #WhereCondition
--INSERT INTO #DemoTbl
--select SUBSTRING(col1,1, CHARINDEX(':',col1,1)-1) MetricName,SUBSTRING(col1, CHARINDEX(':',col1,1)+1,LEN(Col1)) CatValue
--from dbo.UF_CSVDataToTable(#FilterSelectedSelected)
SET #QueryString='SELECT SERIAL FROM Logical.Demographic D
WHERE '+#WhereCondition+' and CountryCategoryId='+cast(#CountryCategoryId as varchar(10))
PRINT #QueryString
insert into #Result
EXEC(#QueryString)
--select * from #Result
END
IF(select top 1 FilterColumn FROM #FilterSelected where FilterColumn='HISPANIC') IS NOT NULL
BEGIN
Delete from #Filter;
DECLARE #Response varchar(20)=null;
Insert into #Filter
Select * from #FilterSelected where FilterColumn='HISPANIC'
select #Response=FilterValue from #Filter;
DECLARE #VariableID int=null;
select #VariableID=SurrogateKeyCounter from MetaData.Metadata_Screener where DBMetricName='HISPANIC';
SET #QueryString_booster='SELECT SERIAL FROM Logical.Response R
WHERE variableid='+cast(#VariableID as varchar(10))+' and CountryCategoryId='+cast(#CountryCategoryId as varchar(10))
+' and ResponseName='''+#Response+''''
PRINT #QueryString_booster
Insert into #Result_booster
EXEC(#QueryString_booster)
END
DECLARE #Final_Result table (SERIAL int)
insert into #Final_Result
select * from #Result
UNION
select * From #Result_booster
select * from #Final_Result
END
I am calling this procedure like this:
declare #ds FilterSelected
insert into #ds values('Hispanic','yes')
#FilterSelected=#ds,#CountryCategoryId=100
DECLARE #DemoTbl TABLE (Serial INT)
Insert into #DemoTbl
EXEC Sp_DemographicFilter_booster #FilterSelected=#ds,
#CountryCategoryId=100
Call SP Sp_DemographicFilter_booster along with unique ID .
Inside Sp_DemographicFilter_booster SP create global table (##) stored result in global table with same unique ID AS ID field
Now when return to main SP access global table with where condition that unique ID

SQL Server query to select all columns of a certain type and also show its max values

I am using SQL Server 2012.
The first part of my query is already answered in this thread. But I also want a second column that will show the corresponding maximum value of that column in its corresponding table.
I have tried this approach: use a function that takes in table name and column name as parameter and return the max value. But it is illegal to use dynamic SQL from a function. Moreover, i cannot seem to call a function from within a SELECT query.
I have also tried using stored procedure, but i cannot figure out how to call it and use it. Please suggest alternative ways to achieve this.
I am new to SQL Server.
Thanks
I think the easiest solution would be stored procedure. As far as I know:
Dynamic SQL can't be placed in functions
Dynamic SQL can't be place in OPENROWSET
I addition, if you write such procedure:
Beware of names containing spaces, qoutes (SQL injection possible)
MAX(column) on non-Indexed columns would require full scan (can be very slow)
Table and column names can be duplicated (placed in differend schemas)
Id duplicates and performance is not a problem, take a look at the following snippet:
CREATE PROC FindMaxColumnValues
#type sysname = '%',
#table sysname = '%'
AS
DECLARE #result TABLE (TableName sysname, ColumnName sysname, MaxValue NVARCHAR(MAX))
DECLARE #tab sysname
DECLARE #col sysname
DECLARE cur CURSOR FOR
SELECT TABLE_NAME TableName, COLUMN_NAME [Column Name]
FROM INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE LIKE #type and TABLE_NAME LIKE #table
OPEN cur
FETCH NEXT FROM cur INTO #tab, #col
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #sql nvarchar(MAX) = 'SELECT '+QUOTENAME(#tab,'''')+' [TableName], '+QUOTENAME(#col, '''')+' [ColumnName], MAX('+QUOTENAME(#col)+') FROM '+QUOTENAME(#tab)
INSERT INTO #result EXEC(#sql)
FETCH NEXT FROM cur INTO #tab, #col
END
CLOSE cur
DEALLOCATE cur
SELECT * FROM #result
Samples:
--MAX of INT's
EXEC FindMaxColumnValues 'INT'
--MAX of INT's in tables matching 'TestTab%'
EXEC FindMaxColumnValues 'INT', 'TestTab%'
--MAX of ALL columns
EXEC FindMaxColumnValues
Results:
TableName ColumnName MaxValue
IdNameTest ID 2
TestTable ID 5
TestTable Number 3
TableName ColumnName MaxValue
TestTable ID 5
TestTable Number 3
TableName ColumnName MaxValue
UpdateHistory UpdateTime 2016-07-14 12:21:37.00
IdNameTest ID 2
IdNameTest Name T2
TestTable ID 5
TestTable Name F
TestTable Number 3
You can use the below SP and enhance it per your Need,
CRETE PROCEDURE Getmaxtablecolval
AS
BEGIN
CREATE TABLE #t
(
tablename VARCHAR(50),
columnname VARCHAR(50),
id INT,
counts INT
)
INSERT INTO #t
SELECT table_name [Table Name],
column_name [Column Name],
NULL,
NULL
FROM information_schema.columns
WHERE data_type = 'INT'
BEGIN TRAN
DECLARE #id INT
SET #id = 0
UPDATE #t
SET #id = id = #id + 1
COMMIT TRAN
DECLARE #RowCount INT
SET #RowCount = (SELECT Count(0)
FROM #t)
DECLARE #I INT
SET #I = 1
DECLARE #Counter INT
DECLARE #TName VARCHAR(50)
DECLARE #CName VARCHAR(50)
DECLARE #DynamicSQL AS VARCHAR(500)
WHILE ( #I <= #RowCount )
BEGIN
SELECT #TName = tablename
FROM #t
WHERE id = #I
SELECT #CName = columnname
FROM #t
WHERE id = #I
SET #DynamicSQL = 'Update #T Set Counts = '
+ '(Select ISNull(Max(' + #CName + '), 0) From '
+ #TName + ') Where Id = '
+ CONVERT(VARCHAR(10), #I)
--PRINT #DynamicSQL
EXEC (#DynamicSQL)
SET #I = #I + 1
END
SELECT *
FROM #t
END
go
Getmaxtablecolval
You can create a procedure out of this:
CREATE PROCEDURE GET_COLUMNS_WITH_MAX_VALUE
#COLUMN_TYPE NVARCHAR(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- DUMMY VARIABLE TO COPY STRUCTURE TO TEMP
DECLARE #DUMMY TABLE
(
TABLE_NAME NVARCHAR(50),
COLUMN_NAME NVARCHAR(50),
MAX_VALUE NVARCHAR(MAX)
)
-- CREATE TEMP TABLE FOR DYNAMIC SQL
SELECT TOP 0 * INTO #TABLE FROM #DUMMY
INSERT INTO #TABLE
(TABLE_NAME, COLUMN_NAME)
SELECT TABLE_NAME, COLUMN_NAME
FROM information_schema.columns where data_type = #COLUMN_TYPE
DECLARE #TABLE_NAME VARCHAR(50) -- database name
DECLARE #COLUMN_NAME VARCHAR(256) -- path for backup files
DECLARE db_cursor CURSOR FOR
SELECT TABLE_NAME, COLUMN_NAME
FROM #TABLE
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #TABLE_NAME, #COLUMN_NAME
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #SQL NVARCHAR(MAX) = 'UPDATE #TABLE SET MAX_VALUE = (SELECT MAX([' + #COLUMN_NAME + ']) FROM [' + #TABLE_NAME + ']) '
+ 'WHERE [COLUMN_NAME] = ''' + #COLUMN_NAME + ''' AND TABLE_NAME = ''' + #TABLE_NAME + '''';
PRINT #SQL
EXEC (#SQL)
FETCH NEXT FROM db_cursor INTO #TABLE_NAME, #COLUMN_NAME
END
CLOSE db_cursor
DEALLOCATE db_cursor
SELECT * FROM #TABLE
DROP TABLE #TABLE
END
GO
Usage:
EXEC GET_COLUMNS_WITH_MAX_VALUE 'INT'
Results:
TABLE1 ID 50
TABLE2 ID 100
TABLE3 CarID 20
TABLE4 StudentID 30

GENERIC STORED PROCEDURE TO AUDIT TABLE UPDATE

Is there a generic stored procedure to audit the table. I have actually made one but I don't think its efficient and the stored procedure is quite long. If someone knows a better way to do it then please help me out...!
This is my table trigger.
ALTER TRIGGER [dbo].[Trigger3]
ON [dbo].[UserInfo]
AFTER Update
AS
BEGIN
SET NOCOUNT ON;
DECLARE #TABLENAME VARCHAR(50)
DECLARE #var varbinary
SELECT * INTO #TEMPINSERTED FROM inserted
SELECT * INTO #TEMPDELETED FROM deleted
SET #var = COLUMNS_UPDATED()
EXEC TetsProc #TEMPINSERTED, #TEMPDELETED, ##PROCID, #var
DROP TABLE #TEMPINSERTED
DROP TABLE #TEMPDELETED
END
This is my stored procedure
ALTER PROCEDURE [dbo].[TetsProc]
( #insertTable varchar(max),
#deleteTable varchar(max),
#IDZ varchar(max),
#var1 varbinary
)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #TABLE AS TABLE (COL_NAME NVARCHAR(MAX))
DECLARE #idTable INT
SELECT #idTable = T.id
FROM sysobjects P JOIN sysobjects T ON P.parent_obj = T.id
WHERE P.id = #IDZ
declare #q1 nvarchar(max),#q2 nvarchar(max)
set #q1 = 'select * from ' + #insertTable
set #q2 = 'select * from ' + #deleteTable
DECLARE #TABLENAME NVARCHAR(250)
SELECT #TABLENAME = OBJECT_NAME(parent_obj)
FROM sysobjects WHERE ID = #IDZ
----RETURN COLUMNS IF THEY ARE UPDATED----
SELECT #idTable = T.id
FROM sysobjects P JOIN sysobjects T ON P.parent_obj = T.id
WHERE P.id = ##procid
DECLARE #Columns_UpdateD VARCHAR(50)
SELECT #Columns_Update = ISNULL(#Columns_Updated + ', ', '') + name
FROM syscolumns
WHERE id = #idTable
AND CONVERT(VARBINARY,REVERSE(#var1)) & POWER(CONVERT(BIGINT, 2), colorder - 1) > 0
select status into #TmpcolumnsUpdated from dbo.ParseByComma(#Columns_UpdateD)
DECLARE #QRY1 NVARCHAR(MAX)
DECLARE #QRY2 NVARCHAR(MAX)
declare #column_name varchar(50)
DECLARE cursorColumnName CURSOR FOR
select status from #TmpcolumnsUpdated
OPEN cursorColumnName
FETCH NEXT FROM cursorColumnName INTO #column_name
WHILE ##FETCH_STATUS = 0
BEGIN
SET #QRY1= 'SELECT '+#column_name + ' FROM '+ #insertTable
SET #QRY2= 'SELECT '+#column_name + ' FROM ' + #deleteTable
DECLARE #tab AS TABLE (OLD_COL VARCHAR(10))
DECLARE #tab1 AS TABLE (NEW_COL VARCHAR(10))
INSERT into #tab EXECUTE sp_executesql #QRY2
INSERT into #tab1 EXECUTE sp_executesql #QRY1
DECLARE #OLD_VALUE VARCHAR(MAX)=(SELECT OLD_COL FROM #tab)
DECLARE #NEW_VALUE VARCHAR(MAX)=(SELECT NEW_COL FROM #tab1)
IF(#OLD_VALUE!=#NEW_VALUE)
BEGIN
INSERT INTO UpdateInfo (Table_Name,Col_Name,Old_Value,New_Value,Time)
(
SELECT
#TABLENAME,
#column_name,
#OLD_VALUE,
#NEW_VALUE,
GETDATE()
)
SELECT * FROM UpdateInfo
END
DELETE FROM #tab
DELETE FROM #tab1
FETCH NEXT FROM cursorColumnName INTO #column_name
END
CLOSE cursorColumnName
DEALLOCATE cursorColumnName
drop table #TmpcolumnsUpdated
END
Looks like a sure way to drag down the performance of your server.
If you are using SQL Server 2012, I'd recommend you to check out Sql Server Audit instead.
If you have to stick with your mechanism, at the very least lose the cursor in the PROC.

How do you use a T-SQL variable within an if OBJECT_ID to check if a table exists?

What I am trying to do with the following code is have it grab all the database names then loop through those databases check to see if the table tblAdminLogin exists and if it does update the password for username 'foo'
I have been using a select statement instead of an update as of yet until it works properly.
declare #databases table
(
PK int IDENTITY(1,1),
dbid int,
name varchar(50)
)
insert into #databases(dbid, name) select dbid, name from master.dbo.sysdatabases
Declare #maxPK int; select #maxPK = MAX(PK) from #databases
Declare #pk int; Set #pk = 1
Declare #name varchar(50)
While #pk <= #maxPK
Begin
Select #name = name from #databases where PK=#pk
if OBJECT_ID(''+#name+'.dbo.tblAdminLogin') IS NOT NULL
Begin
Select password from #name.dbo.tblAdminLogin where username = 'foo'
--Update #name.dbo.tblAdminLogin Set password='bar' where username = 'foo'
End
Set #pk = #pk + 1
End
The main code in question is
Select #name = name from #databases where PK=#pk
if OBJECT_ID(''+#name+'.dbo.tblAdminLogin') IS NOT NULL
Begin
Select password from #name.dbo.tblAdminLogin where username = 'foo'
--Update #name.dbo.tblAdminLogin Set password='bar' where username = 'foo'
End
Edit: Added T-SQL to title since I am using SQL Server
Edit: Fixed the Typo .dbl. to the correct .dbo.
Dynamic SQL.
Untested
declare #SQL varchar(max) -- varchar(8000) if on SQL Server 2000 or earlier
While #pk <= #maxPK
Begin
Select #name = name from #databases where PK=#pk
if OBJECT_ID(''+#name+'.dbo.tblAdminLogin') IS NOT NULL
Begin
set #SQL = 'update ' + quotename(#name) + '.dbo.tblAdminLogin Set password=''bar'' where username = ''foo'''
exec (#SQL)
End
set #PK = #PK + 1
End
References:
QUOTENAME
EXECUTE
Edit: general note on types, not asked for by OP:
The database name is of type SYSNAME which, last I checked, is equivelent to a NVARCHAR(128). Storing that value in a VARCHAR type has the chance of losing information. Small chance at some site because of the names they would choose, but a chance none the less.
declare #databases table
(
PK int IDENTITY(1,1),
dbid int,
name sysname
)
insert into #databases(dbid, name) select dbid, name from master.dbo.sysdatabases
Declare #maxPK int; select #maxPK = MAX(PK) from #databases
Declare #pk int; Set #pk = 1
Declare #name sysname -- so that
declare #SQL nvarchar(4000)
While #pk <= #maxPK
Begin
Select #name = name from #databases where PK=#pk
if OBJECT_ID(#name+N'.dbo.tblAdminLogin') IS NOT NULL
Begin
set #SQL = N'update ' + quotename(#name) + N'.dbo.tblAdminLogin Set password=''bar'' where username = ''foo'''
exec (#SQL)
End
set #PK = #PK + 1
End
Alternative:
EXEC sp_MSForEachDB
'Use [?]; if object_id(''tblAdminLogin'') is not null Select password from tblAdminLogin where username = ''foo'''
I might do something like this:
exec sp_msforeachdb '
if (object_id(''[?].[dbo].[tblAdminLogin]'', ''U'')) is not null
begin
update table [?].[dbo].[tblAdminLogin] Set password=''bar'' where username = ''foo''
select ''?'', username, password from [?].[dbo].[tblAdminLogin] where username = ''foo''
end
'

Resources