I'm converting a date to a string in a Stored Procedure, to send to a BCP. This works but the formatting in the CSV appears to open as dd-mm-yyyy despite using type 103 which should show dd/mm/yyyy' (see https://msdn.microsoft.com/en-us/library/ms187928.aspx)
Code:
USE [Database]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[spExcelIntoTableMainReport]
(
#tableName sysname,
#xModuleID varchar(Max)
)
AS
BEGIN
---------------------------------------
DECLARE #FilePath varchar(150)
SELECT #FilePath = 'C:\Sites\Reposts\'
--------------------------------------------------------------
DECLARE #sql NVARCHAR(MAX)
---------------------------------------
DECLARE #tableCREATE NVARCHAR(2500)
SET #tableCREATE = 'CREATE TABLE ' + #tableName + '
(
[ID] VARCHAR(200),
DateFrom varchar(100),
DateTo varchar(100)
)'
EXEC (#tableCREATE)
---------------------------------------
SET #sql = '
INSERT INTO ' + #tableName + '
(
ID,
DateFrom ,
DateTo
)
VALUES
(
''ID'',
''Date From (DD/MM/YYYY)'' ,
''Date to (DD/MM/YYYY)''
)'
EXEC (#sql)
SET #sql = '
INSERT INTO ' + #tableName + '
(
ID,
DateFrom ,
DateTo
)
SELECT ID,
LTRIM(RTRIM(CONVERT(varchar(10),cast(ModuleDateStart as Date),103))),
LTRIM(RTRIM(CONVERT(varchar(10),cast(ModuleDateComplete as Date),103) )),
FROM TBLRESULTS'
EXEC (#sql)
--------- Now we have a table create the CSV ----------
DECLARE #sql1 varchar(8000)
SELECT #sql1 = 'bcp DATABASE+ #tableName + ' out ' + #FilePath + ''+ #tableName + '.csv -c -t, -T -S '+ ##servername
EXEC master..xp_cmdshell #sql1
END
Related
Below is the script that i have used which shows that i have used BCP process and some shell script to generate the extracts. we need to take the data from sql table and dump as it is in table to flat file. So these can be used to load in hive tables and qlick apps for users to have a look at the data.
ALTER Procedure [dbo].[GenerateEAPExtracts] #tblName NVARCHAR(MAX), #filePath VARCHAR(255)
As
BEGIN
IF OBJECT_ID('tempdb..#Temp1') IS NOT NULL
BEGIN
Drop table #Temp1
END
--DECLARE #tblName NVARCHAR(MAX) = 'BMI.BMI_Invites'
DECLARE #SchemaName NVARCHAR(50)
DECLARE #tbl varchar(100)
DECLARE #DBName varchar(100)
SET #tbl= Replace(#tblname,(Left(#tblname,(LEN(#tblname)-(charindex('.',reverse(#tblname))-1)))),'');
SET #SchemaName= SUBSTRING(#tblName,1,LEN(Left(#tblname,(LEN(#tblname)-(charindex('.',reverse(#tblname))-1))))-1);
DECLARE #SQL NVARCHAR(MAX)=''
DECLARE #SQL1 NVARCHAR(MAX)=''
DECLARE #ColConvert NVARCHAR(MAX)=''
DECLARE #ColName NVARCHAR(MAX)=''
DECLARE #ColName1 NVARCHAR(MAX)=''
DECLARE #ColName2 NVARCHAR(MAX)=''
DECLARE #Dt NVARCHAR(MAX)=''
DECLARE #I INT=1, #COUNT INT;
Create table #Temp1(
ID INT IDENTITY(1,1),
[DBName] [nvarchar](255) NULL,
[TableName] [nvarchar](255) NULL,
[Attributes] [nvarchar](MAX) NULL,
[DataType] [nvarchar](MAX) NULL,
[TceMdf_Dt] [date] NULL
)
SET #SQL = 'INSERT INTO #Temp1 select TABLE_CATALOG as [DBName],
Table_Name as [TableName],
Column_name as [Attributes],
DATA_TYPE as [DataType],
getdate() as [TceMdf_Dt]
from Information_schema.columns where Table_Schema ='''+ #SchemaName +''' AND table_name = '''+#tbl+''''
print #SQL
--EXEC SP_EXECUTESQL #SQL
EXEC(#SQL)
SELECT #SQL1='Select #totCnt= count(1) FROM Information_schema.columns where Table_Schema ='''+ #SchemaName +''' AND table_name = '''+#tbl+''''
print #SQL1
EXECUTE sp_executesql #SQL1, N'#totCnt int OUTPUT', #totCnt=#COUNT OUTPUT
WHILE #I <= #COUNT
BEGIN
SELECT #ColName = Attributes FROM #Temp1 WHERE ID = #I AND [TableName]=#tbl;
SELECT #DBName = DBName FROM #Temp1 WHERE ID = #I AND [TableName]=#tbl;
SELECT #Dt= DataType FROM #Temp1 WHERE ID = #I AND [TableName]=#tbl AND [Attributes]=#ColName
IF #Dt ='Date' or #Dt='Datetime' or #Dt='Decimal' or #Dt='Int' or #Dt='Float' or #Dt='datetime2' or #Dt='Numeric' or #Dt='Real' or #Dt='bit' or #Dt='tinyint'
BEGIN
SET #ColConvert='convert(varchar(25),['+#ColName+'],120)'
--EXECUTE sp_executesql #ColConvert
SET #ColName2 = #ColName2 + ',' + #ColConvert
--EXECUTE sp_executesql #ColName2
END
ELSE
BEGIN
SET #ColName2 = #ColName2 + ',' + '['+#ColName+']'
--EXECUTE sp_executesql #ColName2
END
SET #ColName1 = #ColName1 +''''+''''+','+''''+''''+ #ColName
--EXECUTE sp_executesql #ColName1
SET #I=#I+1;
END
SET #ColName1=RIGHT(#ColName1, LEN(#ColName1) - 3) + ''''''
SET #ColName2=LTRIM(RTRIM(RIGHT(#ColName2, LEN(#ColName2) - 1)))
--print #ColName1
--print #ColName2
--DECLARE #filePath VARCHAR(255)
DECLARE #fileName VARCHAR(255)
DECLARE #sqlCommand VARCHAR(MAX)
DECLARE #sqlCommand1 VARCHAR(MAX)
DECLARE #sqlCommand2 VARCHAR(MAX)
DECLARE #qry nvarchar(max)='(SELECT MaxCDate from '+#DBName+'.config.EAP_Extracts where TableName= '''''+ #tbl +''''')'
print #qry
--exec(#qry)
--SET #filePath = 'C:\'
SET #fileName = #tbl + '_'
+ CONVERT(VARCHAR, GETDATE(), 112) + '.csv'
set #sqlCommand = 'SQLCMD.EXE -S LocalHost -d TCE_WW -E -h -1 -s"|" -W -Q "set nocount on;SELECT ' +#ColName1+ ' ; Select ' +#ColName2+ ' FROM '+#DBName+'.' +#tblName+ ''
print(#sqlCommand)
set #sqlCommand1 =' where TceMdf_Dt > '+ #qry +''
set #sqlCommand2 ='" -o "'+#filePath+#fileName+'" -f 65001'
--declare #chkQry varchar(max) = #sqlCommand+#sqlCommand1+#sqlCommand2
--print(#chkQry)
Update config.EAP_Extracts Set [SqlMaxQuery]=#sqlCommand+#sqlCommand1+#sqlCommand2 where TableName=''+#tbl+''
declare #CommandString varchar(max)= (select distinct 'EXEC xp_cmdshell '+''''+[SqlMaxQuery]+'''' from config.EAP_Extracts where TableName=''+#tbl+'')
--declare #CommandString varchar(max)= 'EXEC xp_cmdshell ' + ''''+#chkQry+''''
print #CommandString
EXEC (#CommandString)
declare #SQLQuery varchar(max)='Update '+#DBName+'.config.EAP_Extracts Set MaxCDate=(Select Max(TceMdf_Dt) from '+ #tblName+') where TableName='''+#tbl+''''
--EXEC xp_cmdshell 'bcp "SELECT ''update_action'',''UserName'',''lastupdate'',''Quote_Num'',''Region'',''ExternalDataReference'',''TceLd_Dt'',''TceMdf_Dt'',''Record_Status'' ; Select LTRIM(RTRIM[update_action]),LTRIM(RTRIM[UserName]),LTRIM(RTRIM[lastupdate]),LTRIM(RTRIM[Quote_Num]),LTRIM(RTRIM[Region]),LTRIM(RTRIM[ExternalDataReference]),convert(varchar(25),LTRIM(RTRIM[TceLd_Dt]),120),convert(varchar(25),LTRIM(RTRIM[TceMdf_Dt]),120),LTRIM(RTRIM[Record_Status]) FROM TCE_WW.BMI.BMI_Invites where TceMdf_Dt > (SELECT MaxCDate from TCE_WW.config.EAP_Extracts where TableName= 'BMI_Invites')" queryout "C:\BMI_Invites_20190722.txt" -T -c -q -y 0 -t"|"'
exec (#SQLQuery)
print(#SQLQuery)
Drop table #Temp1
END
I'm trying to write a stored procedure in SQL Server that gets the columns as parameters. The user will select the column name from a combo box and will write the searched value for that column on a textbox.
I've been searching how to do this and so far i have this:
ALTER PROCEDURE [dbo].[SP_Select_TBL_Folio]
#cant int,
#Column1 nvarchar(50),
#Value1 nvarchar(50),
#Column2 nvarchar(50),
#Value2 nvarchar(50),
#Column3 nvarchar(50),
#Value3 nvarchar(50)
AS
BEGIN
declare #query nvarchar (max)
SET NOCOUNT ON;
if #cant = 1
BEGIN
set #query = 'SELECT * FROM TBL_Folio WHERE ' + #Column1 + ' LIKE '+ #Value1 + ' ORDER BY 1 DESC';
exec sp_executesql #query, N' '
END
else
BEGIN
if #cant = 2
BEGIN
set #query = 'SELECT * FROM TBL_Folio WHERE ' + #Column1 + ' LIKE '+ #Value1 + ' AND ' + #Column2 + ' LIKE '+ #Value2 + ' ORDER BY 1 DESC';
exec sp_executesql #query, N' '
END
ELSE
if #cant = 3
BEGIN
set #query = 'SELECT * FROM TBL_Folio WHERE ' + #Column1 + ' LIKE '+ #Value1 + ' AND ' + #Column2 + ' LIKE '+ #Value2 + ' AND ' + #Column3 + ' LIKE '+ #Value3 + ' ORDER BY 1 DESC';
exec sp_executesql #query, N' '
END
END
END
The user can send 1 to 3 values, for that I have the parameter #cant, this code works but I want to know if there is a better way to do this or how can I improve this stored procedure.
I think what you have is fine if you need to do it in an SP rather than client side. I would probabably initialize the query to the 'select * from TBL_Folio" and then append the LIKES after each if. I would also caution against using SELECT * so your client side doesn't blow up if a field gets added to the table.
If you have a need to check a variable number of fields rather than just up to 3, you can do a table-valued parameter and build up your query by looping through. Here is an example:
ALTER PROCEDURE [dbo].[GetFilteredInvoices]
#FilterColumns ColumnValueType READONLY
AS
BEGIN
SET NOCOUNT ON;
declare #columnName varchar(50), #columnValue varchar(MAX), #query nvarchar(MAX), #count int
set #query='SELECT InvoiceNumber, InvoiceDate, Customer from Invoices '
set #count=0
set #columnName=''
while exists(select * from #FilterColumns where ColumnName>#ColumnName)
begin
set #columnName=(select min(ColumnName) from #FilterColumns where ColumnName>#columnName)
if #count=0
set #query=#query+'WHERE '
else
set #query=#query+'AND '
set #query=#query+ (select ColumnName+' Like ''%'+ColumnValue+'%'' ' from #filterColumns where ColumnName=#columnName)
set #count=#count+1
end
exec sp_executesql #query
END
Here is the table valued type I used:
CREATE TYPE [dbo].[ColumnValueType] AS TABLE(
[ColumnName] [varchar](50) NULL,
[ColumnValue] [varchar](max) NULL
)
GO
Now this will take any number of columns and values to apply the filter.
Here is an example call to the procedure:
DECLARE #RC int
DECLARE #FilterColumns [dbo].[ColumnValueType]
insert into #filterColumns
Values('InvoiceNumber','345')
,('Customer','67')
EXECUTE #RC = [dbo].[GetFilteredInvoices]
#FilterColumns
I think you can perhaps improve the way that you handle your input parameters by getting rid of the #cant parameter. You can also improve the way that you build up the conditions, at the moment you are not handling the situations where only #Column2 and #Value2 or only #Column3 and #Value3 is set (perhaps it is not needed in your case, but it is still good practice to handle these types of scenarios)
CREATE PROCEDURE SP_Select_TBL_Folio
#Column1 NVARCHAR(50) = NULL,
#Value1 NVARCHAR(50) = NULL,
#Column2 NVARCHAR(50) = NULL,
#Value2 NVARCHAR(50) = NULL,
#Column3 NVARCHAR(50) = NULL,
#Value3 NVARCHAR(50) = NULL
AS
BEGIN
SET NOCOUNT ON;
DECLARE
#P1 NVARCHAR(500),
#P2 NVARCHAR(500),
#P3 NVARCHAR(500),
#SQL NVARCHAR(MAX)
IF (#Column1 IS NULL OR #Column1 = '') AND (#Value1 IS NULL OR #Value1 = '')
BEGIN
-- This will build up dynamic SQL to always select records even if #Column1
-- and #Value1 is not set. This obvisously all depends on your requirements
-- and if you still need to select records if the parameters are not set, otherwise
-- it can be changed to ' WHERE ThePrimaryKeyColumn = 0'
SET #P1 = ' WHERE ThePrimaryKeyColumn > 0'
END
ELSE
BEGIN
SET #P1 = 'WHERE ' + #Column1 + ' LIKE ' + '''' + #Value1 + ''''
END
IF (#Column2 IS NULL OR #Column2 = '') AND (#Value2 IS NULL OR #Value2 = '')
BEGIN
SET #P2 = ''
END
ELSE
BEGIN
SET #P2 = ' AND ' + #Column2 + ' LIKE ' + '''' + #Value2 + ''''
END
IF (#Column3 IS NULL OR #Column3 = '') AND (#Value3 IS NULL OR #Value3 = '')
BEGIN
SET #P3 = ''
END
ELSE
BEGIN
SET #P3 = ' AND ' + #Column3 + ' LIKE ' + '''' + #Value3 + ''''
END
SET #SQL = 'SELECT * FROM TBL_Folio
[P1]
[P2]
[P3]'
-- Here we set all the conditions
SET #SQL = REPLACE(#SQL, '[P1]', #P1);
SET #SQL = REPLACE(#SQL, '[P2]', #P2);
SET #SQL = REPLACE(#SQL, '[P3]', #P3);
-- This will be replaced by EXEC(#SQL)
PRINT #SQL
END
So now you can for instance execute
EXEC SP_Select_TBL_Folio
which will give you
SELECT * FROM TBL_Folio
WHERE ThePrimaryKeyColumn > 0
or you can execute
EXEC SP_Select_TBL_Folio 'Column1','Value1'
which will give you
SELECT * FROM TBL_Folio
WHERE Column1 LIKE 'Value1'
or you can execute
EXEC SP_Select_TBL_Folio NULL,NULL,'Column2','Value2'
which will give you
SELECT * FROM TBL_Folio
WHERE ThePrimaryKeyColumn > 0
AND Column2 LIKE 'Value2'
I'm not going to list all the permutations, I'm sure you get my point.
SET NOCOUNT ON;
DECLARE #sql NVARCHAR(MAX)
--,#DBName VARCHAR(30)
--SET #jobNumber=417133
--SELECT #DBName = DataBaseName,'tdis', #server = '[' + isnull(server,'s-portaldb1') + ']'
--from tdLogging.dbo.tblJobDbLookup where jobnumber = #jobNumber
DROP TABLE #Actual
CREATE TABLE #Actual (
jobnumber INT
,firstNameCounts VARCHAR(25)
,lastNameCounts VARCHAR(25)
,address1Counts VARCHAR(25)
,address2Counts VARCHAR(25)
,cityCounts VARCHAR(25)
,stateCounts VARCHAR(25)
,zipCounts VARCHAR(25)
,inHomeDateCounts VARCHAR(25)
)
SET #sql = 'INSERT INTO #actual (jobnumber,firstNameCounts,lastNameCounts , address1Counts, address2Counts, cityCounts, stateCounts, zipCounts, inHomeDateCounts) '
SET #sql = #sql + ' Select s.jobnumber, count(s.firstName) AS [firstNameCounts], Count (s.lastName) AS [lastNameCounts], Count (s.Address1) As [address1Counts], Count (s.address2)-Count (address2) AS '
SET #sql = #sql + ' [address2Counts], Count (s.City) AS [cityCounts], Count (s.State) AS [stateCounts], Count (s.Zip) AS [zipCounts], Count (jb.inHomeDate) AS [inHomeDateCounts] '
SET #sql = #sql + ' From [s-portaldb1].[tdis_417133].[dbo].[tblStandardFinal] s '
SET #sql = #sql + ' INNER JOIN [s-printstream].[tdSchedule2].[dbo].[tblJobTicketActions] jb '
SET #sql = #sql + ' ON jb.psFlagJobNumber = s.jobNumber '
SET #sql = #sql + ' where jobNumber = #jobNumber '
SET #sql = #sql + ' group by jobNumber '
PRINT #SQL
EXEC sp_executesql #sql
,N'#JobNumber Varchar(25)'
,#JobNumber = 417133;
SELECT *
FROM #Actual
I am trying to get this code to run dynamically and i wanted to have the "[s-portaldb1].[tdis_417133]" come on the run means dynamically.
any help would be greatly appreciated. Thank you
Not sure I know what "come on the run" means, but if you are trying to make the server name dynamic in your dynamic SQL, just add a parameter for your server name and then introduce that to your SQL using something like the following:
DECLARE #ServerName varchar(100) = '[s-portaldb1].[tdis_417133]'
SET #sql = #sql + ' From ' + #Servername + '.[dbo].[tblStandardFinal] s '
I would like to ask how am I going to return the count(*) because every time I call the stored procedure, it just prints the result.
Here is the code :
ALTER PROCEDURE sp_returnCount
#tblname sysname
, #colname sysname
, #key varchar(10)
AS
DECLARE #sql nvarchar(4000)
DECLARE #num INT
DECLARE #params NVARCHAR (4000)
SELECT #sql = 'SELECT COUNT(*) ' +
' FROM dbo.' + quotename(#tblname) +
' WHERE ' + quotename(#colname) + ' LIKE #key'
EXEC sp_executesql #sql, N'#key varchar(10)', #key
--just prints 5 or any numbers...
I'd like to return the count(*) to use it in another query. Thanks in advance.
ALTER PROCEDURE sp_returnCount
#tblname sysname
, #colname sysname
, #key varchar(10)
AS
DECLARE #sql nvarchar(4000)
DECLARE #num INT
DECLARE #params NVARCHAR (4000)
DECLARE #count int
SELECT #sql = 'SELECT #count = COUNT(*) ' +
' FROM dbo.' + quotename(#tblname) +
' WHERE ' + quotename(#colname) + ' LIKE #key'
EXEC sp_executesql #sql, N'#key varchar(10), #count int OUTPUT', #key, #count OUTPUT
I am trying this in SQL Server and it throws an error:
ALTER PROCEDURE [dbo].[GET_TEXT_DETAIL]
#id UNIQUEIDENTIFIER,
#table VARCHAR(255),
#field VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sql VARCHAR(200)
SET #sql = 'select ' + QUOTENAME(#field) + ' from ' + QUOTENAME(#table) + ' where ID = ' + QUOTENAME(#id)
EXEC (#sql)
END
I get this error:
Msg 207, Level 16, State 1, Line 1
Invalid column name 'CFC2776A-6EE1-E511-A172-005056A218B0'.
Is there any way to do this so I don't have to make a bunch or procedures to pull text from a bunch of different tables?
QUOTENAME has optional second parameter quote char, so you were close and this could be solved by:
... QUOTENAME(#id, '''')
but the most proper way for this case is passing the parameter:
set #cmd = '
SELECT t.' + QUOTENAME(#field) + '
FROM ' + QUOTENAME(#table) + ' t
WHERE t.ID = #ID'
exec sp_executesql #cmd, N'#ID uniqueidentifier', #ID
And server will be able to reuse plan as #srutzsky mentioned. Because #ID is no longer part of a query text and #cmd text remains the same for different #ID (and same #table+#field).
ALTER PROCEDURE [dbo].[GET_TEXT_DETAIL]
(
#id UNIQUEIDENTIFIER,
#table SYSNAME,
#field SYSNAME
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQL NVARCHAR(MAX)
SET #SQL = '
SELECT ' + QUOTENAME(#field) + '
FROM ' + QUOTENAME(#table) + '
WHERE ID = ''' + CAST(#id AS VARCHAR(36)) + ''''
--PRINT #SQL
EXEC sys.sp_executesql #SQL
END