I have a complicated batch script involving multiple BCP commands that load SQL server with flat file data. I am using a branch statement that logs the result of the command into a log file. This is all working fine.
The result is also logged in an SQL table as a success or failure. What I am trying to do is, upon failure, insert the contents of the log file into the SQL log table using what I thought was a simple redirect. It isn't working.
Here is what I am doing in a batch file in a Win Server 2012 environment:
BCP (the parameters here don't matter) >> %LogFile% (
MOVE %FileName% to Archive/%FileName%
sqlcmd -E -Q "EXEC spImportLog 'SUCCESS', %FileName%, ''
) || (
SET /p LogText=<%LogFile%
sqlcmd -E -Q "EXEC spImportLog 'FAILED', %FileName%, %LogText%
)
This code executes without error. The true part of the statement works fine.
The false part executes fine but I end up with empty string instead of
the contents of %LogText%.
When I run this from a command prompt, the SET looks like this:
SET /p LogText<0Log_2016_9_23.log
The %LogFile% is a variable because it is dynamically named at run time based on today's date. I don't know where the 0 after the less than sign is coming from, or if it is the source of my problem. Any ideas?
YADXP.
SET /p LogText=<%LogFile%
setlocal enabledelayedexpansion
sqlcmd -E -Q "EXEC spImportLog 'FAILED', %FileName%, !LogText!
endlocal
should work. See the billion or so SO entries about "delayed expansion"
As I said, set /p var=<filename will set the variable from the first line of the file. Since the file accumulates values and is initially sset to contain just one line (AAUI) 'None' then that is the value that will be read from the file.
Try
for /f "usebackqdelims=" %%a in ("%LogFile%") do set "logtext=%%a"
setlocal enabledelayedexpansion
sqlcmd -E -Q "EXEC spImportLog 'FAILED', %FileName%, !LogText!
endlocal
which should read every line of %logfile% and assign to logtest the value (of each line) in turn, so that when the for terminates, logtext will have the value of the last line of the file.
Okay, thanks for the posts. It doesn't sound like what I want to do is possible. At least not the way I am trying to do it. What I wanted is to store the entire contents of %LogFile% in a variable as a textstream, and then insert that text stream into a varchar column in SQL server. In retrospect, I wasn't clear enough in my initial post exactly the problem I was trying to solve. I know I can store the command results (multiple lines) in a temporary table in SQL Server. It is just that it requires using xp_cmdshell, which I was hoping to avoid.
Related
I have a batch file that extracts one row from a database and uses that data as a variable to use the value to be a filename, and exports data as text file.
It works fine except for exporting two text files.
One of the two files is the correct file.
The other one is the unnecessary file. The filename is ".txt" and has the same data as the first one.
Here is my bat file:
SET SQLCMD=sqlcmd -S server -d db -Q "set NOCOUNT
on; select name from t1" -h-1
FOR /F "usebackq delims=, tokens=1" %%i IN (`%SQLCMD%`) DO (
CALL :PROCESSING %%i
)
:PROCESSING
SET COL1=%1
bcp "SELECT * FROM t1" queryout "C:\Export\%COL1%.txt." -S server -T -c
What do I need to fix to get only one file?
Since I am new to coding, if anyone could help, that would be very appreciated.
Thank you,
I know this is very similar to this SO question, but I've modified the script to do what I'm trying to do and when I run the batch file it just closes right after hitting Enter after entering the company ID.
I need to check that the company id the user enters when the batch script runs is valid. I'm using user-entered values elsewhere in the script, so I'm sure that's correct, but I'm not getting why the script doesn't run as-is.
Here's my script:
#SETLOCAL ENABLEDELAYEDEXPANSION
#ECHO OFF
ECHO Enter the Company ID the data is for
SET /p _COMPANYID=Company ID:
SET _INSTANCE=someinstance
SET _DATABASE=somedb
for /f %%a in (
sqlcmd -b -S %_INSTANCE% -d %_DATABASE% -E -l 2 -Q "SET NOCOUNT ON; select count(*) from glb_companies where companyid = %_COMPANYID%"
)
do set _RESULT=%%a
echo %_RESULT%
#pause
I've tried the sqlcmd line with and without single quotes. The switches I have in the sqlcmd are what I'm using elsewhere and I've also tried it just with the switches from the other SO post. Nothing's worked for me yet.
I have the following situation:
I need to execute a SQL Server stored procedure compiled on the server, passing some values. I'm creating a batch file to do this task. Something like this:
#ECHO OFF
ECHO Enter the initial date in YYYYMMDD format (eg. 20171201):
SET /p pi_dte_ini=
ECHO Enter the final date in YYYYMMDD format (eg. 20171231):
SET /p pi_dte_end=
sqlcmd -Q "exec my_on_the_server_sp %pi_dte_ini%, %pi_dte_end%" -S server\instance
PAUSE
The problem is that I have to execute this .bat on a user's machine of our network. This machine don't have SQL Server installed, so it can't run sqlcmd. Any suggestions are welcome.
Regards!
You do not have to echo then run set /p. Instead add the echo text as part of the set /p
To execute sqlcmd remotely, use wmic
#Echo off
Set /p "pi_dte_ini=Set the initial date with YYYYMMDD format (eg: 20171201) and press Enter: "
Set /p "pi_dte_end=Set the final date with YYYYMMDD format (eg: 20171231) and press Enter: "
wmic /node:"servername" process call create ""cmd.exe /c sqlcmd -Q "exec my_on_the_server_sp %pi_dte_ini%, %pi_dte_end%" -S server\instance"
Pause
I cannot test this as I do not have sqlcmd, but you will probably need to adjust the double quotes in the wmic call.
My goal is to write a batch script that will delete all of the cache names from a particular cache server.
The code I wrote below errors because it cannot execute the AppFabric PowerShell commands. It returns "Remove-Cache -CacheName blahblah" is not a recognized as an internal or external command.
I guess what I need to figure out and I need help from you guys is how can I use the shell script FOR /F command but yet be able to execute AppFabric PowerShell commands.
I tried adding the line:
powershell.exe -noexit -command "Import-Module DistributedCacheAdministration;Use-CacheCluster"
in the beginning of the batch script to first bring up the PowerShell window, import the AppFabric module and then run the batch script. But because PowerShell doesn't recognize FOR /F, it bombs there. I'm trying to delete multiple cachenames, but I'm just too not advanced enough to do it. HELP!
:
#echo off
REM using PING and batch line retrieval... only IP address info is called out from ping request
FOR /F "tokens=2,3" %%A IN ('ping %computername% -n 1 -4') DO IF "from"== "%%A" set "IP=%%~B"
echo %IP:~0,-1%
REM GET-CacheClusterHealth > C:\output.txt
REM FIND /n /i "NamedCache" C:\output.txt > C:\results.txt
FOR /F "tokens=4" %%i in (C:\results.txt) DO "Remove-Cache -CacheName %%i"
DEL "C:\output.txt"
DEL "C:\results.txt"
ECHO ALL Cache names have been deleted from Cache Server %IP:~0,-1%
Pause
To be honest it looks like you are making this way more complicated than it needs to be. PowerShell is the way things are moving so you may want to look into how it works a bit more. What you probably need is something along the lines of (kind of pseudo-code since I don't have the actual cmdlet to reference):
Import-Module DistributedCacheAdministration
Use-CacheCluster
$ServerName = "SomeServer01"
$ServerPort = "22233"
Get-Cache -HostName $ServerName -CachePort $ServerPort | ForEach{Remove-Cache $_.CacheName}
Now I don't know what is returned from Get-Cache but I imagine that it returns an array of things and from looking at your script one of the properties is NamedCache, which is what you want to work with. The above example would import the module needed to perform the commands. Then it sets the cache cluster to the current host, assign a variable to the name of a server that you want to work with, and then another variable to the port for it. Lastly it performs the Get-Cache command against the specified host and port, and sends the results of that to a ForEach loop that performs the Remove-Cache command against all of the items returned's NamedCache property. As I said before I assume it returns an array of objects which contain a NamedCache property.
As for FOR /F in PowerShell, what you could do if you really want to go that route is something like:
Get-Content Results.txt | ForEach{Remove-Cache -CacheName $_.Split(" ")[3]}
That gets the contents of the file, and then for each line it splits that line at each space, and references the 4th item (PowerShell's Split method will turn the string into an array of strings, and since arrays start at record 0 in PowerShell [3] references the 4th string in the array).
I have recently had SSMS 2008 re-installed on my laptop
When I click "New Query..", I am now prompted to select the encoding for the file, something I was never asked to do before
I have associated sql againt "SQL Query Editor with Encoding" in the Text Editor section of the Option and restarted SSMS
What can I do to associate with an encoding as I don't want to select everytime I do a new query or open an existing sql file
As per the workaround posted by Fakher Halim on Microsoft Azure Feedback Forums.
I had the same issue. Git wouldn't show any differences in history
(besides "Binary files a/x.sql and b/x.sql differ). So I clicked
Tools=>Options=>Environments=>International Settings. Changed the
Language from "English" to "Same as Microsoft Windows". Now GIT DIFF
works perfectly well -- reports version difference normally!
Based on the advice given elsewhere (https://feedback.azure.com/forums/908035-sql-server/suggestions/32892454-need-a-way-to-set-the-default-encoding-for-query-f) I've hacked up a "command script" to attempt to "change the default encoding" to UTF-8 with a BOM. The script works by writing a UTF-8 w/ BOM template to a SQLFile.sql file within the Program Files tree of SQL Server. It has worked once on my machine, but that doesn't mean that it's bugfree or 100% safe. USE AT OWN RISK!
According to "Microsoft's" response in that thread:
The default for how files are saved is determined by the way the main template file SQLFile.sql located at C:\Program Files\Microsoft SQL Server\90\Tools\Binn\VSShell\Common7\IDE\sqlworkbenchprojectitems\Sql. If you save this file using ANSI encoding, then subsequent new query sessions will use this encoding.
Note that on my machine I found the template at a different path so I wrote the script to find any file matching that name under either Program Files. It seems like a silly enough name that false collisions should be rare.
If passed no arguments (or any arguments other than what it expects) then it should do a dry-run. Make sure to run it without administrative privileges first. It will at least find any applicable files and you can decide then if you want to proceed with the script or modify the files yourself.
To run the script for real then pass a first argument of "force". This is the dangerous part. Heed caution. To run the script to completion without pausing for user input then pass a second argument of "dontpause" (this can be passed with an empty first argument to skip pausing during a dry-run).
I choose UTF-8 because it's 7-bit ASCII compatible, it supports the vast majority of languages and characters you'll ever care to script, it stores Western text and source code very efficiently, and it's source control/text patch friendly. The template at the bottom of the script contains a byte-order mark (BOM) to signal editors that it is not ISO-8859-1 or some other incompatible default 8-bit encoding. Be sure it isn't lost when you copy/paste. Save the actual batch script as ASCII (or compatible; without a BOM!). The command processor chokes on a UTF-8 BOM.
#echo off
setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION || exit /b 1
if "x%1" == "xforce" (
echo Force enable. Danger Will Robinson! This means that I'm going to
echo attempt to move files and write a new file to replace them. This
echo is potentially destructive if there are any bugs in this script.
echo In particular, if there are any unrelated files with the name
echo sqlfile.sql under your Program Files directories then they'll be
echo corrupted.
echo.
echo This script is going to require elevated privileges to write to
echo Program Files. Execute the Command Prompt application as an
echo administrator to proceed ^(should be harmless to try without
echo elevation first^).
echo.
echo I RECOMMEND YOU _DO NOT_ RUN THIS SCRIPT FROM WINDOWS EXPLORER
echo BECAUSE YOU MAY HAVE A HARDER TIME READING THE OUTPUT. Start a
echo Command Prompt and run it there.
echo.
if not "x%2" == "xdontpause" (
echo Now is a good time to Ctrl+C ^(and Y^).
pause
)
) else (
echo Dry-run enabled. Pass a lone argument of "force" to go for real. 1>&2
echo Be careful running the script several times. Your template backup
echo will be overwritten and lost.
)
set paths="C:\Program Files (x86)\SQLFile.sql" "C:\Program Files\SQLFile.sql"
for /f "tokens=*" %%f in ('dir /a /b /s %paths% 2^>NUL') do #(
echo.
echo Found: %%f
if "x%1" == "xforce" (
echo Moving to: %%f.orig
echo.
echo If you ^(or anything else^) has made any changes to your template
echo then you should be able to recover your template from the backup
echo file above ^(not yet, once you continue^) ^(alternatively,
echo recover the template from the source file now^).
if not "x%2" == "xdontpause" (
pause
)
move "%%f" "%%f.orig" || exit /b 1
)
echo.
echo Writing a standard UTF-8 template with byte-order mark ^(BOM^).
echo Feel free to open this file up afterward and manually set the
echo encoding preferred. You can also replace it with your own
echo template text.
if not "x%2" == "xdontpause" (
pause
)
set ok=0
rem Read in myself, look for the __BEGIN__ marker and write
rem subsequent lines to the file.
for /f "tokens=*" %%g in (%~dpf0) do #(
if !ok! == 1 (
if "x%1" == "xforce" (
if "x%%g" == "x." (
echo.
echo.>>"%%f"|| exit /b 1
) else (
echo %%g
echo %%g>>"%%f"|| exit /b 1
)
)
) else (
if "%%g" == "__BEGIN__" (
echo.
echo Found marker. Starting write on next ^(non-empty^) line... 1>&2
echo.
set ok=1
)
)
)
)
exit /b 0
Below is the SQL template. Lines containing only a dot (.) represent
blank lines. Actual blank lines will be lost.
__BEGIN__
BEGIN TRANSACTION;
.
SET XACT_ABORT ON;
.
.
.
ROLLBACK;
--COMMIT;
In SQL Server Management Studio, select Tools/Options then expand "Text Editor" and add the extension "sql" and map it to "SQL Query Editor".
The solution works if you are working with ASCII characters. If the sql contains characters that require explicit encoding (as determined by the SQL editor) then you will must select an encoding. The issue comes into play when creating files in both the SQL editor and other editor (NotePad++), then editing those files in the other editor. NotePad++ saves files without the header and can guess the encoding. The SQL editor on the other hand always requires the encoding header once certain characters are used.
Previous answers have suggested using Tools→Options→Environments→International Settings, but this option is not present in SSMS 17.2.
Instead, you can go to File→Save As..., click the arrow on the "Save" button, and select "Save with Encoding".
I am such an idiot - I changed the association to "SQL Query Editor" and it now all works fine
The "with Encoding" bit should really have tipped me off!