I had created a db named as Suri's _DB and had below query is failing when executed. If the db name is given without single quote the query is executing successfully.
The query is
USE [master];
IF EXISTS (SELECT 1 FROM tempdb..sysobjects WHERE [Id] = OBJECT_ID('tempdb..#tmp_filegroups'))
BEGIN
DROP TABLE #tmp_filegroups
END
CREATE TABLE #tmp_filegroups
(
[DbName] nvarchar(128),
[DbId] int,
[GroupName] nvarchar(128),
[GroupId] int,
[IsFileStream] bit
)
IF EXISTS (SELECT 1 FROM tempdb..sysobjects WHERE [Id] = OBJECT_ID('tempdb..#tmp_dbandlogfiles'))
BEGIN
DROP TABLE #tmp_dbandlogfiles
END
CREATE TABLE #tmp_dbandlogfiles
(
[DbName] nvarchar(128),
[DbId] int,
[GroupId] int,
[Name] nvarchar(128),
[FileName] nvarchar(260),
[Size] float,
[IsReadOnlyMedia] bit,
[IsReadOnly] bit,
[IsOffline] bit,
[IsSparse] bit,
[IsPrimaryFile] bit,
[SpaceUsed] float,
[FileType] int
)
IF EXISTS (SELECT 1 FROM tempdb..sysobjects WHERE [Id] = OBJECT_ID('tempdb..#tmp_fulltextcatalogfiles'))
BEGIN
DROP TABLE #tmp_fulltextcatalogfiles
END
CREATE TABLE #tmp_fulltextcatalogfiles
(
[DbName] nvarchar(128),
[DbId] int,
[Name] nvarchar(128),
[Path] nvarchar(260)
)
DECLARE #DB NVARCHAR(128)
DECLARE #DBID int
DECLARE #CMD NVARCHAR(MAX)
DECLARE Databases CURSOR FAST_FORWARD FOR
SELECT name,dbid FROM master..sysdatabases
WHERE name in (N'Suri''s _DB')
OPEN Databases
FETCH NEXT FROM Databases INTO #DB, #DBID
WHILE (##FETCH_STATUS = 0)
BEGIN
BEGIN TRY
SELECT #CMD = 'use ' + '[' + #DB + ']' + '; select N''' + #DB + ''' as [DbName],' + CAST(#DBID as varchar(30)) + ' as [DbId],s.name as [GroupName],s.data_space_id as [GroupId], CAST(case s.type when ''FD'' then 1 else 0 end AS bit) AS [IsFileStream] FROM sys.filegroups as s ORDER by [GroupId] ASC'
INSERT INTO #tmp_filegroups execute(#CMD)
SELECT #CMD = 'use ' + '[' + #DB + ']' + '; select N''' + #DB + ''' as [DbName],' + CAST(#DBID as varchar(30)) + ' as [DbId],s.data_space_id as [GroupId],s.name AS [Name],s.physical_name AS [FileName],s.size * CONVERT(float,8) AS [Size],s.is_media_read_only AS [IsReadOnlyMedia],s.is_read_only AS [IsReadOnly],CAST(case s.state when 6 then 1 else 0 end AS bit) AS [IsOffline],s.is_sparse AS [IsSparse],CAST(CASE s.file_id WHEN 1 THEN 1 ELSE 0 END AS bit) AS [IsPrimaryFile],CAST(fileproperty(s.name,''SpaceUsed'') AS float) * CONVERT(float,8) AS [SpaceUsed], Type AS [FileType] FROM sys.database_files as s'
INSERT INTO #tmp_dbandlogfiles execute(#CMD)
SELECT #CMD = 'use ' + '[' + #DB + ']' + '; select N''' + #DB + ''' as [DbName],' + CAST(#DBID as varchar(30)) + ' as [DbId],cat.name as [Name],cat.path as [Path] FROM sys.fulltext_catalogs AS cat ORDER by [Name] ASC'
INSERT INTO #tmp_fulltextcatalogfiles execute(#CMD)
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() AS ERRMESS
END CATCH
FETCH NEXT FROM Databases INTO #DB, #DBID
END
CLOSE Databases
DEALLOCATE Databases
select [DbName],[DbId],[GroupName],[GroupId],[IsFileStream] from #tmp_filegroups
DROP TABLE #tmp_filegroups
Why this is failing?
I tried escaping the single quotes
When you build the sql query string, the dbname's single quote is not terminated. Replace any single quotes to 2 single quotes to terminate the character.
SELECT #CMD = 'use ' + '[' + #DB + ']' + '; select N''[' + replace(#DB, '''', '''''') + ']'' as [DbName],' + CAST(#DBID as varchar(30)) + ' as [DbId],s.name as [GroupName],s.data_space_id as [GroupId], CAST(case s.type when ''FD'' then 1 else 0 end AS bit) AS [IsFileStream] FROM sys.filegroups as s ORDER by [GroupId] ASC'
INSERT INTO #tmp_filegroups execute(#CMD)
SELECT #CMD = 'use ' + '[' + #DB + ']' + '; select N''[' + replace(#DB, '''', '''''') + ']'' as [DbName],' + CAST(#DBID as varchar(30)) + ' as [DbId],s.data_space_id as [GroupId],s.name AS [Name],s.physical_name AS [FileName],s.size * CONVERT(float,8) AS [Size],s.is_media_read_only AS [IsReadOnlyMedia],s.is_read_only AS [IsReadOnly],CAST(case s.state when 6 then 1 else 0 end AS bit) AS [IsOffline],s.is_sparse AS [IsSparse],CAST(CASE s.file_id WHEN 1 THEN 1 ELSE 0 END AS bit) AS [IsPrimaryFile],CAST(fileproperty(s.name,''SpaceUsed'') AS float) * CONVERT(float,8) AS [SpaceUsed], Type AS [FileType] FROM sys.database_files as s'
INSERT INTO #tmp_dbandlogfiles execute(#CMD)
SELECT #CMD = 'use ' + '[' + #DB + ']' + '; select N''[' + replace(#DB, '''', '''''') + ']'' as [DbName],' + CAST(#DBID as varchar(30)) + ' as [DbId],cat.name as [Name],cat.path as [Path] FROM sys.fulltext_catalogs AS cat ORDER by [Name] ASC'
INSERT INTO #tmp_fulltextcatalogfiles execute(#CMD)
Related
I have the following script where i want to insert into a table where column name can be passed as comma delimited values. Please suggest different approaches to achieve the following output.
Declare #col_by_source varchar(250) = 's1,s2,s3',
#column_by_target varchar(250) = 'c1,c2,c3',
#SQLString nvarchar(max)
Set #SQLString = 'INSERT INTO [dbo].[sourceTable] (
['+#col_by_source+'] )'
set #SQLString = #SQLString+' '+'SELECT '
Select #SQLString = #SQLString + QUOTENAME(split.a.value('.', 'VARCHAR(100)')) + ' AS '+#col_by_source+','
FROM (SELECT Cast ('<M>' + Replace(#column_by_target, ',', '</M><M>')+ '</M>' AS XML) AS Data) AS A
CROSS apply data.nodes ('/M') AS Split(a);
Set #SQLString = LEFT(#SQLString, LEN(#SQLString) - 1) + ')'
Set #SQLString = #SQLString + 'FROM tableA_source'
print #SQLString
OUTPUT:
INSERT INTO [dbo].[sourceTable] (
[s1,s2,s3] ) SELECT [c1] AS s1,s2,s3,[c2] AS s1,s2,s3,[c3] AS s1,s2,s3 FROM tableA_source
Expected Output:
INSERT INTO [dbo].[sourceTable] (
[s1,s2,s3] ) SELECT [c1] AS s1, [c2] AS s2,[c3] AS s3
FROM tableA_source
Make it as simple. You won't need an alias while doing insert....select.
try like this,
DECLARE #col_by_source VARCHAR(250) = 's1,s2,s3'
,#column_by_target VARCHAR(250) = 'c1,c2,c3'
,#SQLString NVARCHAR(max)
SET #SQLString = 'INSERT INTO [dbo].[sourceTable] (
' + #col_by_source + ' )'
SET #SQLString = #SQLString + ' ' + 'SELECT '
SELECT #SQLString = #SQLString + QUOTENAME(split.a.value('.', 'VARCHAR(100)')) + ' ,'
FROM (
SELECT Cast('<M>' + Replace(#column_by_target, ',', '</M><M>') + '</M>' AS XML) AS Data
) AS A
CROSS APPLY data.nodes('/M') AS Split(a);
SET #SQLString = LEFT(#SQLString, LEN(#SQLString) - 1) + ''
SET #SQLString = #SQLString + 'FROM tableA_source'
PRINT #SQLString
I have a timed sync that references a remote database. The sync uses "Select *...". There have been some changes to the local DB structure, and now the sync fails of course because the columns are different.
How can I compare the two tables?
To get the local columms, I can do:
SELECT * -- COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH
FROM information_schema.columns
WHERE table_name = 'Items'
ORDER BY ordinal_position
And to get the remote columns I can do:
EXECUTE [WebServ].[WebDB].dbo.sp_executesql
N'SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH FROM
INFORMATION_SCHEMA.COLUMNS
WHERE table_name like ''ITEMS_Web'''
But how would I put them together so it just shows me which columns have been added on the local table? I guess I just don't know how to get the results from the Execute command into a useable form so I could do a JOIN or something... Forgive my n00bieness. This is MSSQL 2008
I have a stored procedure to modify archive tables for me automatically.
I have modified it for you, leave the #COMMIT_CHANGES=0 and it will print out the alters required to update the 2nd table to match the first.
Be sure you fix the database and owner in the SET statements to match your own database tables.
I have disabled the EXEC that could potentially alter your table in case you accidentally set #COMMIT_CHANGES to 1... un-comment it if you want the #COMMIT_CHANGES flag to actually execute alter codes. If nothing is returned the tables match.
Edit: I am storing the commands in a table for email to myself, but I removed the email code from this example.
This should give a good foundation for anything you need it to do.
DECLARE #TABLENAME VARCHAR(100), #TABLENAME2 VARCHAR(100), #COMMIT_CHANGES BIT, #SSERVERNAME VARCHAR(100)
SET #TABLENAME='database.dbo.ITEMS' --local
SET #TABLENAME2='database.dbo.ITEMS_WEB' --remote
SET #SSERVERNAME = 'WEBSERV' --remote server
SET #COMMIT_CHANGES=0 -- set to 1, and it WILL change your remote table
SET NOCOUNT ON
DECLARE #SQL VARCHAR(MAX)
DECLARE #DB1 SYSNAME, #OWNER1 SYSNAME, #TABLE1 SYSNAME
DECLARE #DB2 SYSNAME, #OWNER2 SYSNAME, #TABLE2 SYSNAME
DECLARE #RECIPIENTS VARCHAR(500), #ENABLEEMAIL BIT
IF #COMMIT_CHANGES = 0 PRINT 'TEST MODE ONLY, CHANGES WILL NOT BE MADE'
-- PARSE TABLE NAME INTO 3 PARTS
SELECT #TABLE1 = PARSENAME(#TABLENAME, 1)
SELECT #OWNER1 = PARSENAME(#TABLENAME, 2)
IF #OWNER1 IS NULL SELECT #OWNER1 = 'DBO'
SELECT #DB1 = PARSENAME(#TABLENAME, 3)
IF #DB1 IS NULL SELECT #DB1 = DB_NAME()
-- PARSE ARCHIVE TABLE NAME INTO 3 PARTS
SELECT #TABLE2 = PARSENAME(#TABLENAME2, 1)
SELECT #OWNER2 = PARSENAME(#TABLENAME2, 2)
IF #OWNER2 IS NULL SELECT #OWNER2 = 'DBO'
SELECT #DB2 = PARSENAME(#TABLENAME2, 3)
IF #DB2 IS NULL SELECT #DB2 = DB_NAME()
-- IF OUR TEMP TABLES EXIST, DROP THEM
IF EXISTS (SELECT * FROM TEMPDB.INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '##T1_MAIN') DROP TABLE ##T1_MAIN
IF EXISTS (SELECT * FROM TEMPDB.INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '##T2_ARCHIVE') DROP TABLE ##T2_ARCHIVE
-- GATHER SCHEMA INFO FOR LIVE TABLE
SET #SQL = 'SELECT TABLE_NAME,
COLUMN_NAME,
DATA_TYPE,
ISNULL(CHARACTER_MAXIMUM_LENGTH,0) AS CHARACTER_MAXIMUM_LENGTH,
ISNULL(NUMERIC_PRECISION,0) AS NUMERIC_PRECISION,
ISNULL(NUMERIC_SCALE,0) AS NUMERIC_SCALE,
IS_NULLABLE,
CAST(0 AS BIT) AS ADD_COLUMN,
CAST(0 AS BIT) AS ALTER_COLUMN
INTO ##T1_MAIN
FROM ' + #DB1 + '.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = ''' + #TABLE1 + '''
AND TABLE_SCHEMA = ''' + #OWNER1 + ''' '
--PRINT #SQL
EXEC(#SQL)
-- CHECK IF TABLES EXIST, ELSE SKIP ALL WORK
IF NOT EXISTS (SELECT * FROM TEMPDB.INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '##T1_MAIN')
BEGIN
PRINT #TABLENAME + ' DOES NOT EXIST, EXITING PROC'
GOTO SKIPWORK
END
-- GATHER SCHEMA INFO FOR ARCHIVE TABLE
SET #SQL = 'SELECT TABLE_NAME,
COLUMN_NAME,
DATA_TYPE,
ISNULL(CHARACTER_MAXIMUM_LENGTH,0) AS CHARACTER_MAXIMUM_LENGTH,
ISNULL(NUMERIC_PRECISION,0) AS NUMERIC_PRECISION,
ISNULL(NUMERIC_SCALE,0) AS NUMERIC_SCALE,
IS_NULLABLE,
CAST(0 AS BIT) AS DROP_COLUMN
INTO ##T2_ARCHIVE
FROM ['+#SSERVERNAME+'].' + #DB2 + '.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = ''' + #TABLE2 + '''
AND TABLE_SCHEMA = ''' + #OWNER2 + ''' '
--PRINT #SQL
EXEC(#SQL)
-- CHECK IF TABLES EXIST, ELSE SKIP ALL WORK
IF NOT EXISTS (SELECT * FROM TEMPDB.INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '##T2_ARCHIVE')
BEGIN
PRINT #TABLENAME2 + ' DOES NOT EXIST, EXITING PROC'
GOTO SKIPWORK
END
-- FLAG NEW COLUMNS
-- COLUMN IN T1 (LIVE) BUT NOT IN T2 (ARCHIVE)
UPDATE T1 SET ADD_COLUMN = 1
FROM ##T1_MAIN T1
LEFT OUTER JOIN ##T2_ARCHIVE T2
ON T1.COLUMN_NAME = T2.COLUMN_NAME
WHERE T2.COLUMN_NAME IS NULL
-- FLAG REMOVED COLUMNS
-- COLUMN IN T2 (ARCHIVE) BUT NOT IN T1 (LIVE)
-- ** NOT DOING ANYTHING WITH THIS **
UPDATE T2 SET DROP_COLUMN = 1
FROM ##T2_ARCHIVE T2
LEFT OUTER JOIN ##T1_MAIN T1
ON T2.COLUMN_NAME = T1.COLUMN_NAME
WHERE T1.COLUMN_NAME IS NULL
-- FLAG ALTERED COLUMNS
-- ONLY NEED WHERE LIVE DATA LENGTH IS > THAN ARCHIVE DATA LENGTH
-- WE WOULDN'T WANT TO SHRINK A COLUMN AND TRUNCATE A VALUE
UPDATE T1 SET ALTER_COLUMN = 1
FROM ##T1_MAIN T1
JOIN ##T2_ARCHIVE T2
ON T1.COLUMN_NAME = T2.COLUMN_NAME
AND (T1.DATA_TYPE <> T2.DATA_TYPE
OR T1.CHARACTER_MAXIMUM_LENGTH > T2.CHARACTER_MAXIMUM_LENGTH
OR T1.NUMERIC_PRECISION > T2.NUMERIC_PRECISION
OR T1.NUMERIC_SCALE > T2.NUMERIC_SCALE
OR (T1.IS_NULLABLE = 'YES' AND T2.IS_NULLABLE = 'NO'))
DECLARE #COLUMN_NAME VARCHAR(100),
#DATA_TYPE VARCHAR(100),
#CHARACTER_MAXIMUM_LENGTH INT,
#NUMERIC_PRECISION INT,
#NUMERIC_SCALE INT,
#IS_NULLABLE VARCHAR(3)
-- CREATE A TEMP TABLE TO HOLD OUR COMMANDS FOR EMAIL
IF EXISTS (SELECT * FROM TEMPDB.INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '##COMMANDLIST') DROP TABLE ##COMMANDLIST
CREATE TABLE ##COMMANDLIST (sText VARCHAR(1000))
DECLARE ALTER_COLUMN CURSOR LOCAL
FOR
SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, NUMERIC_SCALE, IS_NULLABLE
FROM ##T1_MAIN
WHERE ALTER_COLUMN=1
OPEN ALTER_COLUMN
FETCH NEXT FROM ALTER_COLUMN INTO #COLUMN_NAME, #DATA_TYPE, #CHARACTER_MAXIMUM_LENGTH, #NUMERIC_PRECISION, #NUMERIC_SCALE, #IS_NULLABLE
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SQL = 'ALTER TABLE ' + #DB2 + '.' + #OWNER2 + '.' + #TABLE2 + ' ALTER COLUMN ' + #COLUMN_NAME + ' ' + CASE
WHEN #DATA_TYPE IN ('NCHAR','NVARCHAR','CHAR','VARCHAR') THEN #DATA_TYPE + ' (' + CAST(#CHARACTER_MAXIMUM_LENGTH AS VARCHAR(15)) + ')'
WHEN #DATA_TYPE IN ('TINYINT','SMALLINT','INT','BIGINT','BIT','UNIQUEIDENTIFIER') THEN #DATA_TYPE
WHEN #DATA_TYPE IN ('DECIMAL','MONEY','FLOAT','NUMERIC') THEN #DATA_TYPE + ' (' + CAST(#NUMERIC_PRECISION AS VARCHAR(15)) + ',' + CAST(#NUMERIC_SCALE AS VARCHAR(15)) + ')'
END
+ ' ' +
CASE
WHEN #IS_NULLABLE = 'YES' THEN 'NULL'
ELSE 'NULL'
END
PRINT #SQL
IF #COMMIT_CHANGES = 1
BEGIN
IF(##SERVERNAME <> #sServerName) SET #SQL = 'EXEC(''' + REPLACE(#SQL,'''','''''') + ''') AT ' + QUOTENAME(#sServerName)
EXEC(#SQL)
END
IF #SQL IS NOT NULL INSERT INTO ##COMMANDLIST (sText) SELECT #SQL
FETCH NEXT FROM ALTER_COLUMN INTO #COLUMN_NAME, #DATA_TYPE, #CHARACTER_MAXIMUM_LENGTH, #NUMERIC_PRECISION, #NUMERIC_SCALE, #IS_NULLABLE
END
CLOSE ALTER_COLUMN
DEALLOCATE ALTER_COLUMN
DECLARE ADD_COLUMN CURSOR LOCAL
FOR
SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, NUMERIC_SCALE, IS_NULLABLE
FROM ##T1_MAIN
WHERE ADD_COLUMN=1
OPEN ADD_COLUMN
FETCH NEXT FROM ADD_COLUMN INTO #COLUMN_NAME, #DATA_TYPE, #CHARACTER_MAXIMUM_LENGTH, #NUMERIC_PRECISION, #NUMERIC_SCALE, #IS_NULLABLE
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SQL = 'ALTER TABLE ' + #DB2 + '.' + #OWNER2 + '.' + #TABLE2 + ' ADD ' + #COLUMN_NAME + ' ' + CASE
WHEN #DATA_TYPE IN ('NCHAR','NVARCHAR','CHAR','VARCHAR') THEN #DATA_TYPE + ' (' + CAST(#CHARACTER_MAXIMUM_LENGTH AS VARCHAR(15)) + ')'
WHEN #DATA_TYPE IN ('TINYINT','SMALLINT','INT','BIGINT','BIT','UNIQUEIDENTIFIER') THEN #DATA_TYPE
WHEN #DATA_TYPE IN ('DECIMAL','MONEY','FLOAT','NUMERIC') THEN #DATA_TYPE + ' (' + CAST(#NUMERIC_PRECISION AS VARCHAR(15)) + ',' + CAST(#NUMERIC_SCALE AS VARCHAR(15)) + ')'
END
+ ' ' +
CASE
WHEN #IS_NULLABLE = 'YES' THEN 'NULL'
ELSE 'NOT NULL'
END
PRINT #SQL
IF #COMMIT_CHANGES = 1
BEGIN
IF(##SERVERNAME <> #sServerName) SET #SQL = 'EXEC(''' + REPLACE(#SQL,'''','''''') + ''') AT ' + QUOTENAME(#sServerName)
-- uncomment this EXEC to make the commit changes flag work...
--EXEC(#SQL)
END
IF #SQL IS NOT NULL INSERT INTO ##COMMANDLIST (sText) SELECT #SQL
FETCH NEXT FROM ADD_COLUMN INTO #COLUMN_NAME, #DATA_TYPE, #CHARACTER_MAXIMUM_LENGTH, #NUMERIC_PRECISION, #NUMERIC_SCALE, #IS_NULLABLE
END
CLOSE ADD_COLUMN
DEALLOCATE ADD_COLUMN
SKIPWORK:
this is my Stored Procedure of MSSQL and I want to be convert this SP to MySQL,but i cant understand what to used instead of 'with' keyword in MySql so any one help me ??? Thanx in Advance!!!!!
ALTER PROCEDURE [dbo].[TPortRateOnKm_SP_List]
#qtype varchar(MAX) = NULL,
#query varchar(MAX)= NULL,
#Sortname varchar(MAX) =NULL,
#sortorder varchar(MAX) =NULL ,
#PageNo int,
#RecordsPerPage int,
#likesearch int
AS
BEGIN
DECLARE #temp INT;
DECLARE #qry varchar(MAX) = '';
DECLARE #qry1 varchar(MAX) = '';
set #temp = (#PageNo - 1) * #RecordsPerPage
If #query is not null and #query <> ''
Begin
Set #qry1= ' Where '+ #query
End
Else
Begin
Set #qry1= ''
End
If #query is not null and #query <> ''
Begin
Set #query= ' Where ('+ #query + ') and (RowNo > ' +
cast(((#PageNo-1) *#RecordsPerPage) as varchar) + ' AND RowNo <= '
+ cast(#PageNo * #RecordsPerPage as varchar)+ ') '
End
Else
Begin
Set #query= ' Where (RowNo > ' + cast(((#PageNo-1) *#RecordsPerPage) as varchar) + ' AND RowNo <= ' + cast(#PageNo * #RecordsPerPage as varchar)+ ') '
End
If #sortorder is not null and #sortorder <> ''
Begin
Set #sortorder= ' Order By '+ #sortorder
End
Else
Begin
Set #sortorder= ' ORDER BY VehicleId'
End
here is 'With' Keyword
set #qry = 'Set dateformat dmy ;WITH CustomTable as
(Select ROW_NUMBER() OVER ( '+ #sortorder+') as RowNo,A.* From
(select Convert(varchar,T.WefDate,103) As WefDate,T.VehicleId as
VehicleId,V.VehicleNo as VehicleNo,T.StartKm,T.EndKm,T.Rate from
TrnRateOnKmRange T left outer join MasterVehicle V on
V.VehicleId=T.VehicleId) A '
Set #qry= #qry + #qry1
Set #qry= #qry + ' )
SELECT CAST(RowNo AS INT) as
RowNo,WefDate,VehicleId,VehicleNo,StartKm,EndKm,Rate
FROM CustomTable'
Set #qry=#qry + #query + #sortorder
EXECUTE (#qry)
END
can any one do this ??
I have a bcp command that is pushing the results of a query into a flat file that is comma delimited unicode. I need the fields to be encapsulated in double quotes with the text identifier being double quotes.
Here's an example of the csv output:
36029,2,Oct 11 2004 1:01AM,4,23537,0.10
Where it needs to be:
"36029","2","Oct 11 2004 1:01AM","4","23537","0.10"
I suspect it uses the -q flag but I'm not sure how to actually use the -q. The MS documentation is not doing much to help me out.
Sorry if this is a dupe, I looked hard I swear!
try this:
Exec Master..xp_Cmdshell 'bcp "SELECT '"' + col1 + '"', '"' + col2+ '"', '"' + col3+ '"'
FROM table1" queryout "C:\mcg1.csv" -c -t,"'
If you extract from within Eclipse it puts double quotes around text and dates. I do this from the view Data Source Explorer. Right click -> Data -> Extract...
You can also utilize SQL servers QuoteName function to specify the column that should have quotes. This also gives the ability to add any character in place of quotes
Exec Master..xp_Cmdshell 'bcp "SELECT QuoteName(col1,Char(34)),QuoteName(col2,Char(34)),... FROM table1" queryout "C:\test.csv" -c -t,"'
Take a look here to learn more
SQL Server BCP Utility Experts Guide
DECLARE #DBName VARCHAR(100) = 'dbname'
,#TableName VARCHAR(100) = 'example'
,#FileNamePath VARCHAR(100) = 'example.csv'
,#MaxRowsPerFile INT = 999999999
,#Resume BIT = 0
,#PrintVarValues BIT = 1
,#ConvertDates BIT = 1
,#QuotedStrings BIT = 0
,#delimitor VARCHAR(1) = ','
--Generate column names as a recordset
DECLARE #columns VARCHAR(8000)
,#columnsas VARCHAR(8000)
,#columnsformatted VARCHAR(8000)
,#sql VARCHAR(8000)
,#HeaderFile VARCHAR(100)
,#DataFile VARCHAR(100)
,#FileCount INT
,#TotalRows INT
,#RowCount INT
,#IntVariable INT
,#SQLString NVARCHAR(4000)
,#ParmDefinition NVARCHAR(512)
,#FileCountName VARCHAR(100)
,#PrimaryColumn NVARCHAR(128)
,#FileExtension VARCHAR(10)
,#Quote1 VARCHAR(10) = ''
,#Quote2 VARCHAR(10) = '';
IF (#QuotedStrings = 1)
BEGIN
SELECT #Quote1 = 'QUOTENAME('
,#Quote2 = ',CHAR(34))'
END
IF (
len(isnull(#DBName, '')) > 1
AND len(isnull(#TableName, '')) > 1
)
BEGIN
EXEC ('USE [' + #DBName + '];')
SELECT #FileCount = 1
,#RowCount = 1
IF (OBJECT_ID(N'dbo.#CreateExcel') IS NOT NULL)
BEGIN
IF (#Resume = 0)
BEGIN
DROP TABLE dbo.#CreateExcel
END
ELSE
BEGIN
SELECT #FileCount = FileCount
,#RowCount = [RowCount]
FROM dbo.#CreateExcel WITH (NOLOCK)
END
END
IF (OBJECT_ID(N'dbo.#CreateExcel') IS NULL)
BEGIN
CREATE TABLE dbo.#CreateExcel (
FileCount INT
,[RowCount] INT
)
INSERT INTO dbo.#CreateExcel (
FileCount
,[RowCount]
)
VALUES (
1
,1
)
END
SELECT #FileExtension = CASE
WHEN CHARINDEX('.', REVERSE(#FileNamePath)) > 1
THEN RIGHT(#FileNamePath, CHARINDEX('.', REVERSE(#FileNamePath)))
ELSE '.XLS'
END
SELECT #FileNamePath = CASE
WHEN CHARINDEX('.', REVERSE(#FileNamePath)) > 1
THEN LEFT(#FileNamePath, LEN(#FileNamePath) - CHARINDEX('.', REVERSE(#FileNamePath)))
ELSE #FileNamePath
END
SELECT #HeaderFile = substring(#FileNamePath, 1, len(#FileNamePath) - charindex('\', reverse(#FileNamePath))) + '\HeaderFile.xls'
SELECT #DataFile = substring(#FileNamePath, 1, len(#FileNamePath) - charindex('\', reverse(#FileNamePath))) + '\DataFile.xls'
SET #SQLString = N'SELECT #Primary_Column = bb.[name] FROM (' + N'SELECT TOP 1 co.[name] ' + N'FROM [' + #DBName + N'].[sys].[objects] ao with (nolock) ' + N' inner join [' + #DBName + N'].[sys].[columns] co with (nolock) ' + N' on ao.object_id = co.object_id ' + N'WHERE ao.[name] = ''' + #TableName + N'''' + N' AND ((co.is_identity=1) ' + N' or (co.column_id =1 and co.IS_NULLABLE=0) ' + N' or (co.system_type_id=36 /*uniqueidentifier*/) ' + N' or (co.system_type_id in (42,61,189) /*datetimes*/)) ' + N'ORDER BY co.is_identity desc, co.column_id asc, co.system_type_id asc) bb';
SET #ParmDefinition = N'#Primary_Column NVARCHAR(128) OUTPUT';
EXECUTE sp_executesql #SQLString
,#ParmDefinition
,#Primary_Column = #PrimaryColumn OUTPUT;
SET #SQLString = N'SELECT #cols=coalesce(#cols+'','','''')+''[''+co.[name]+'']'', ' + N'#colsas=coalesce(#colsas+'','','''')+''' + #Quote1 + '''''''+co.[name]+''''''' + #Quote2 + ''', ' + N'#colsformatted=coalesce(#colsformatted+'','','''')+CASE WHEN co.[system_type_id] in (98,167,175,231,239,241) THEN
''' + #Quote1 + 'REPLACE(REPLACE([''+co.[name]+''],CHAR(13),CHAR(32)),CHAR(10),CHAR(32))' + #Quote2 + '''
WHEN co.[system_type_id] in (35,99) THEN
''' + #Quote1 + 'REPLACE(REPLACE(CAST([''+co.[name]+''] AS VARCHAR(8000)),CHAR(13),CHAR(32)),CHAR(10),CHAR(32))' + #Quote2 + '''
WHEN ' + LTRIM(RTRIM(CAST(#ConvertDates AS INT))) + N'=1 AND co.[system_type_id] in (40,42,58,61) THEN
''' + #Quote1 + 'CONVERT(varchar(10),[''+co.[name]+''],101)+'''''''' ''''''''+LEFT(RIGHT(CONVERT(varchar(24),[''+co.[name]+''],109),12),8)+'''''''' ''''''''+RIGHT(LTRIM(RTRIM(CONVERT(varchar(24),[''+co.[name]+''],100))),2)' + #Quote2 + '''
ELSE ''[''+co.[name]+'']''
END ' + N'FROM [' + #DBName +
N'].[sys].[objects] ao with (nolock) ' + N' inner join [' + #DBName + N'].[sys].[columns] co with (nolock) ' + N' on ao.object_id = co.object_id ' + N'WHERE ao.[name] = ''' + #TableName + N'''';
SET #ParmDefinition = N'#cols VARCHAR(8000) OUTPUT, #colsas VARCHAR(8000) OUTPUT, #colsformatted VARCHAR(8000) OUTPUT';
EXECUTE sp_executesql #SQLString
,#ParmDefinition
,#cols = #columns OUTPUT
,#colsas = #columnsas OUTPUT
,#colsformatted = #columnsformatted OUTPUT;
--Create HeaderFile.XLS
SET #sql = 'exec master..xp_cmdshell ''bcp "SELECT ' + REPLACE(REPLACE(#columnsas, CHAR(34), CHAR(34) + CHAR(34)), CHAR(39), CHAR(39) + CHAR(39)) + '" queryout "' + #HeaderFile + '" -c -t ' + CASE
WHEN #delimitor IS NULL
THEN ''
ELSE #delimitor
END + ' -T'''
IF (#PrintVarValues = 1)
BEGIN
PRINT #sql
END
EXEC (#sql)
SET #SQLString = N'SELECT #Total_Rows = count(1) from [' + #DBName + N']..[' + #TableName + N'] with (nolock)';
SET #ParmDefinition = N'#Total_Rows INT OUTPUT';
EXECUTE sp_executesql #SQLString
,#ParmDefinition
,#Total_Rows = #TotalRows OUTPUT;
WHILE (#RowCount <= #TotalRows)
BEGIN
--Create incremental filename for each chuck of rows from table in database
IF (#PrintVarValues = 1)
BEGIN
PRINT 'Percent Complete: ' + ltrim(rtrim(cast(cast((#RowCount * 100) / #TotalRows AS INT) AS VARCHAR(10)))) + '%'
END
SET #FileCountName = #FileNamePath + Right(REPLICATE('0', 3) + ltrim(rtrim(CAST(#FileCount AS VARCHAR(4)))), 4) + #FileExtension
--populate data into incremental filename
SET #sql = 'exec master..xp_cmdshell ''bcp "SELECT ' + #columnsformatted + ' FROM ( SELECT ROW_NUMBER() OVER (ORDER BY [' + #PrimaryColumn + '] ASC) AS [ROW_NUMBER], ' + #columns + ' FROM [' + #DBName + ']..[' + #TableName + '] ) foo WHERE [ROW_NUMBER] BETWEEN ' + LTRIM(RTRIM(CAST(#RowCount AS NVARCHAR(10)))) + ' AND ' + LTRIM(RTRIM(CAST(#RowCount - 1 + #MaxRowsPerFile AS NVARCHAR(10)))) + '" queryout "' + #DataFile + '" -c -t ' + CASE
WHEN #delimitor IS NULL
THEN ''
ELSE #delimitor
END + ' -T'''
IF (#PrintVarValues = 1)
BEGIN
PRINT #sql
END
EXEC (#sql)
--Merge headerfile.xls with incremental filename
SET #sql = 'exec master..xp_cmdshell ''copy /b ' + #HeaderFile + '+' + #DataFile + ' ' + #FileCountName + ''''
IF (#PrintVarValues = 1)
BEGIN
PRINT #sql
END
EXEC (#sql)
--update TempCreateExcel table with running values in case needing to abort and restart from checkpoint reached.
SELECT #FileCount = #FileCount + 1
,#RowCount = #RowCount + #MaxRowsPerFile
UPDATE dbo.#CreateExcel
SET FileCount = #FileCount
,[RowCount] = #RowCount
END
IF (#PrintVarValues = 1)
BEGIN
PRINT 'Percent Complete: 100%'
END
DROP TABLE [dbo].#CreateExcel
END
use:
select col1, col2, quotename(col3, '\"') from table1 -- backslash before double quote to escape the "
I want to get all the transactions applied on a specific table in SQL Server 2008.
I found the last time a table was updated using this script:
SELECT OBJECT_NAME(OBJECT_ID) AS DatabaseName, last_user_update,*
FROM sys.dm_db_index_usage_stats
WHERE database_id = DB_ID( 'DBName')
AND OBJECT_ID=OBJECT_ID('tableName')
I want to know all the transactions (Inserts, Updates, Deletes) for that table, and their datetime, and the query applied.
What is the best way to do this?
The only way to do this in a reasonable amount of time is to use a third party tool(as Martin said in first comment) such as ApexSQL Log that can read transaction log and get the information you need.
Note that in order for this to work your database has to be in a full recovery mode because that’s when SQL Server logs full transaction details that can be reconstructed later.
Another option is to investigate how to use undocumented fn_dblog function but this will take you a lot more time and you won’t be able to read detached logs or transaction log backups.
creating a trigger which will create a new table Emp_audit and add new tuples to it whenever any change is made to table employee
create trigger my_trigger on Employees
AFTER INSERT, UPDATE, DELETE
AS
DECLARE #What varchar(30);
DECLARE #Who varchar(30);
DECLARE #for int;
DECLARE #At time;
DECLARE #COUNTI int;
DECLARE #COUNTD int;
select #COUNTI = COUNT(*) from inserted;
select #COUNTD = COUNT(*) from deleted;
set #Who = SYSTEM_USER;
set #At = CURRENT_TIMESTAMP;
if( #COUNTD = 0 and #COUNTI = 1)
begin
set #What = 'insert';
select #for = EmployeeID from inserted i;
end
else
begin
if( #COUNTD = 1 and #COUNTI = 0)
begin
set #What = 'delete';
select #for = EmployeeID from deleted i;
end
else
begin
set #What = 'update';
select #for = EmployeeID from inserted i;
end
end
INSERT INTO EMP_Audit Values (#What, #Who, #for, #At);
You would be much better off setting up auditing for this need rather than trying to extract this information retrospectively from the transaction log.
If you are on Enterprise Edition you could use the built in SQL Server Audit functionality, otherwise it should be relative straight forward to log the desired information via triggers.
You could create your own transaction logs
Step 1: Create your own table for transaction logs
CREATE TABLE [dbo].[TransactionLogs](
[TransactionLogID] [bigint] IDENTITY(1,1) NOT NULL,
[Query] [nvarchar](max) NOT NULL,
[DateCreated] [datetime] NOT NULL,
CONSTRAINT [PK_TransactionLogs] PRIMARY KEY CLUSTERED
(
[TransactionLogID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
Step 2: Create stored procedure that create logs. (Note: Replace YourTablePKColumn with your table primary key column.)
create procedure [dbo].[sp_CreateQueryLogs]
(
#Query nvarchar(max) = null output,
#TableName nvarchar(100),
#YourTablePKColumn nvarchar(30),
#QueryTypeID tinyint --0 insert, 1 update, 2 delete
)
as
begin
declare #object_id bigint, #column_name nvarchar(100), #collation_name nvarchar(50), #column_name_id nvarchar(100) = null, #column_names nvarchar(max) = '', #column_values nvarchar(max) = '', #column_names_create nvarchar(max) = '', #values nvarchar(max) = '', #user_type_id int, #max_length nvarchar(10), #type_name nvarchar(50), #CreateTempTable nvarchar(max) = '', #is_nullable bit, #value nvarchar(max) = ''
create table #tmpValues(ColumnValues nvarchar(max))
insert into #tmpValues(ColumnValues)
exec('select CAST ( ( select * from ' + #TableName + ' where YourTablePKColumn = ' + #YourTablePKColumn + '
FOR XML PATH(''tr''), TYPE
) AS NVARCHAR(MAX) )')
select #values = ColumnValues from #tmpValues
if #QueryTypeID = 0 --insert
set #Query = 'insert into ' + #TableName + '('
else if #QueryTypeID = 1 --update
set #Query = 'update ' + #TableName + ' set '
else if #QueryTypeID = 2 --dalete
set #Query = 'delete ' + #TableName + ' '
select #object_id = object_id from sys.tables where name = #TableName
if not cursor_status('local','columnCursor') <= -1
begin
close columnCursor;
deallocate columnCursor;
end
declare columnCursor cursor local for
select name, user_type_id, convert(nvarchar(10), max_length), is_nullable from sys.columns where object_id = #object_id order by column_id ;
open columnCursor;
fetch next from columnCursor
into #column_name, #user_type_id, #max_length, #is_nullable;
while ##FETCH_STATUS = 0
begin
select #type_name = name, #collation_name = collation_name from sys.types where user_type_id = #user_type_id
if #column_name_id is null
set #column_name_id = #column_name
else
begin
set #column_names += #column_name + ', '
declare #value_keys_start nvarchar(max) = '<' + #column_name + '>', #value_keys_end nvarchar(max) = '</' + #column_name + '>'
if charindex(#value_keys_start,#values,1) = 0
begin
if #QueryTypeID = 0 --insert
set #column_values += 'null,'
else if #QueryTypeID = 1 --update
set #column_values += #column_name + ' = null,'
end
else
begin
if #QueryTypeID = 0 --insert
if #collation_name is null and not (#type_name like '%date%' or #type_name like '%time%')
set #column_values += substring(#values, charindex(#value_keys_start,#values,1) + len(#value_keys_start), charindex(#value_keys_end,#values,1) - (charindex(#value_keys_start,#values,1) + len(#value_keys_start))) + ','
else if #type_name like '%date%' or #type_name like '%time%'
set #column_values += '''' + replace(substring(#values, charindex(#value_keys_start,#values,1) + len(#value_keys_start), charindex(#value_keys_end,#values,1) - (charindex(#value_keys_start,#values,1) + len(#value_keys_start))),'T',' ') + ''','
else
set #column_values += '''' + replace(substring(#values, charindex(#value_keys_start,#values,1) + len(#value_keys_start), charindex(#value_keys_end,#values,1) - (charindex(#value_keys_start,#values,1) + len(#value_keys_start))),'''','''''') + ''','
else if #QueryTypeID = 1 --update
if #collation_name is null and not (#type_name like '%date%' or #type_name like '%time%')
set #column_values += #column_name + '=' + substring(#values, charindex(#value_keys_start,#values,1) + len(#value_keys_start), charindex(#value_keys_end,#values,1) - (charindex(#value_keys_start,#values,1) + len(#value_keys_start))) + ','
else if #type_name like '%date%' or #type_name like '%time%'
set #column_values += #column_name + '=' + '''' + replace(substring(#values, charindex(#value_keys_start,#values,1) + len(#value_keys_start), charindex(#value_keys_end,#values,1) - (charindex(#value_keys_start,#values,1) + len(#value_keys_start))),'T',' ') + ''','
else
set #column_values += #column_name + '=' + '''' + replace(substring(#values, charindex(#value_keys_start,#values,1) + len(#value_keys_start), charindex(#value_keys_end,#values,1) - (charindex(#value_keys_start,#values,1) + len(#value_keys_start))),'''','''''') + ''','
end
end
fetch next from columnCursor
into #column_name, #user_type_id, #max_length, #is_nullable;
end
if not cursor_status('local','columnCursor') <= -1
begin
close columnCursor;
deallocate columnCursor;
end
if #QueryTypeID = 0 --insert
set #Query += substring(#column_names,1,len(#column_names) - 1) + ')
values (' + substring(#column_values,1,len(#column_values) - 1) + ')'
else if #QueryTypeID = 1 --update or delete
set #Query += substring(#column_values,1,len(#column_values) - 1) + ' where YourTablePKColumn = ' + #YourTablePKColumn
else
set #Query += ' where YourTablePKColumn = ' + #YourTablePKColumn
end
Step 3: Created trigger to table you want to have transaction logs
CREATE TRIGGER trg_MyTrigger ON YouTableName
AFTER INSERT, DELETE, UPDATE
AS
BEGIN
SET NOCOUNT ON;
declare #TableName nvarchar(100) = 'YouTableName', #Query nvarchar(max), #QueryTypeID tinyint, #YourTablePKColumn nvarchar(30)
if exists(select * from deleted) and exists(select * from inserted)
begin
set #QueryTypeID = 1
if not cursor_status('local','updatedCursor') <= -1
begin
close updatedCursor;
deallocate updatedCursor;
end
declare updatedCursor cursor local for
select cast(YourTablePKColumn as nvarchar(30)) from inserted;
open updatedCursor;
fetch next from updatedCursor
into #YourTablePKColumn;
while ##FETCH_STATUS = 0
begin
exec dbo.sp_CreateQueryLogs #Query = #Query output, #TableName = #TableName, #YourTablePKColumn = #YourTablePKColumn, #QueryTypeID = #QueryTypeID
insert into TransactionLogs
(Query, DateCreated)
values (#Query,getdate())
fetch next from updatedCursor
into #YourTablePKColumn;
end
if not cursor_status('local','updatedCursor') <= -1
begin
close updatedCursor;
deallocate updatedCursor;
end
end
else if exists(select * from deleted) and not exists(select * from inserted)
begin
set #QueryTypeID = 2
if not cursor_status('local','deletedCursor') <= -1
begin
close deletedCursor;
deallocate deletedCursor;
end
declare deletedCursor cursor local for
select cast(YourTablePKColumn as nvarchar(30)) from deleted;
open deletedCursor;
fetch next from deletedCursor
into #YourTablePKColumn;
while ##FETCH_STATUS = 0
begin
exec dbo.sp_CreateQueryLogs #Query = #Query output, #TableName = #TableName, #YourTablePKColumn = #YourTablePKColumn, #QueryTypeID = #QueryTypeID
insert into TransactionLogs
(Query, DateCreated)
values (#Query,getdate())
fetch next from deletedCursor
into #YourTablePKColumn;
end
if not cursor_status('local','deletedCursor') <= -1
begin
close deletedCursor;
deallocate deletedCursor;
end
end
else
begin
set #QueryTypeID = 0
if not cursor_status('local','insertedCursor') <= -1
begin
close insertedCursor;
deallocate insertedCursor;
end
declare insertedCursor cursor local for
select cast(YourTablePKColumn as nvarchar(30)) from inserted;
open insertedCursor;
fetch next from insertedCursor
into #YourTablePKColumn;
while ##FETCH_STATUS = 0
begin
exec dbo.sp_CreateQueryLogs #Query = #Query output, #TableName = #TableName, #YourTablePKColumn = #YourTablePKColumn, #QueryTypeID = #QueryTypeID
insert into TransactionLogs
(Query, DateCreated)
values (#Query,getdate())
fetch next from insertedCursor
into #YourTablePKColumn;
end
if not cursor_status('local','insertedCursor') <= -1
begin
close insertedCursor;
deallocate insertedCursor;
end
end
END
GO