2017年10月2日 星期一

bat & sqlcmd 筆記

會寫 bat 主要是因為每次改完程式之後會需要更新好幾個環境
ex.今天的修改紀錄資料夾、公司環境的資料夾等等
單純的複製到固定名稱的資料夾大致上沒啥問題
比較大的問題是【今天的修改紀錄資料夾】的"今天",
代表的我每天都要複製到不同的日期資料夾去...
估狗了一下,

@set A=%date:/=%
@set B=%A:~0,8%
@set C="\\UPDATE\%B%\DLL\"

假設今天是 2017/10/2 用上面的寫法可以得到
C="\\UPDATE\20171002\DLL\"

可是每次都要先去檢查有沒有件資料夾,所以...

IF NOT EXIST %C%. (MKDIR %C%.)

上面的寫法可以檢查有沒有 \20171002\DLL 的資料夾,
如果沒有,則執行 MKDIR 建立

到了以上,自動複製 dll 的沒有問題了
再來就是 SQL 檔的問題了,每次還又一個一個更新 DB 很煩,
真想請一個小助手來幫忙...
所以又找到了 sqlcmd ,
但是發現 sqlcmd 在每一版的 SQL SERVER 提供的命令、參數,甚至是寫法都不一樣
所以首先就先指定 sqlcmd 的路徑,我是直接設定變數指定

@set SQLPATH="C:\Program Files (x86)\Microsoft SQL Server\Client SDK\ODBC\130\Tools\Binn\sqlcmd"

然後指定好下面的參數

@set TEST= -S FRANKIE\sql2014 -U sa -P 1234567 -d FRANKIE_TEST -i 
  • -S 指定 SQL SERVER 主機\Instances
  • -U 指定登入的帳號
  • -P 指定登入帳號的密碼
  • -d 指定DB
  • -i 要執行的 SQL 檔案
假設我們要執行的是 AAA.SQL

%SQLPATH%%TEST% AAA.SQL

大概會組合出

C:\Program Files (x86)\Microsoft SQL Server\Client SDK\ODBC\130\Tools\Binn\sqlcmd -S FRANKIE\sql2014 -U sa -P 1234567 -d FRANKIE_TEST -i AAA.SQL

不過我想執行資料夾下面的所有 SQL 檔,
所以再度估狗一下,最後用 FOR 處理,
直接在 CMD 視窗測試 FOR 的時候都OK,
可是從 BAT 檔執行的時候卻一直跳出錯誤,
原來變數在 CMD 視窗的時候是 %i
但是在 BAT 檔的時候要變成 %%i
最後寫在 BAT 的 FOR 如下:

for %%i in (*.sql) do %SQLPATH%%TEST% %%i

(*.sql) 會幫我把執行所在的資料夾中的 SQL 全部都找出來,
然後執行 do 後面的事情。

寫到這裡,更新資料夾與 DB 對我來說變成只是 double click 了,喔耶~~~

但是事情還是做不完,囧rz

無法載入檔案或組件 'Microsoft.SqlServer.Management.Sdk.Sfc, Version=11.0.0.0 ...

前陣子因為 NB 的 SSD 快滿了,
所以只好開始移除一些用不太到的東西,
然後今天就發生問題了....
果然東西是不可以亂移除的....

問題發生在 VS2013 要從資料庫拉 Table 到 DataSet 的時候,
跳出了下面的訊息
---------------------------
伺服器總管
---------------------------
無法加入資料連接。

無法載入檔案或組件 'Microsoft.SqlServer.Management.Sdk.Sfc, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91' 或其相依性的其中之一。 系統找不到指定的檔案。
---------------------------
確定   
---------------------------

上網找了錯誤訊息,大概是 SQL SERVER 2012 被我移除的關係
網路上的說法大致上是要補回下面這幾個就可以


  • SQLSysClrTypes.msi (這個要先安裝)
  • SharedManagementObjects.msi 
  • SqlServer2005_XMO.msi 


但是因為我已經安裝了更新版本的 SQL SERVER 2014/2016 了,
所以 SQLSysClrTypes.msi 無法安裝上!
網路上是說要退版啦~~~
不過後來我直接安裝了 SharedManagementObjects.msi 之後就可以了。

但是我比較想知道如何更換 VS 2013 裡面指定的 Version=11.0.0.0 ?

補充下載點 Microsoft® SQL Server® 2012 SP1 功能套件

2015年1月22日 星期四

Delphi - Goto 用法


世事真的很難料...
怎知莫名其妙的會從 C# 倒退回來寫 Delphi!
更怎知會退到 BDE 這麼這麼有年紀的技術...
好啦!抱怨完啦~~~

沒想到從沒寫過 goto 的我會在這個摸門需要...
查了一下大概就會長的像下面這個樣子


是說這樣不寫 goto 可以用甚麼?程式碼如下:

var
  mr: Word;
  I, J: Integer;
  label CheckFile;
begin
  CheckFile:
  if not FileExists(fileName) then
  begin
    mr := MessageDlg('檔案' + fileName + '不存在!', mtError, mbAbortRetryIgnore, 0);
    case mr of
      mrAbort: Abort;
      mrRetry: goto CheckFile;
      mrIgnore: Exit;
    end;
  end;

收工...(雙手合十)

2014年6月17日 星期二

OLE error 800A03EC

今天跑程式,產生報表在 EXCEL ,
五分鐘前還好好的,結果突然就跑出一個錯誤訊息
【OLE error 800A03EC】?
不知道為什麼,一開始還以為 Oracle 的權限又跑掉了,
跑了權限的 SQL 結果還是一樣,
跑了別張報表發現也一樣?
把程式關掉重開還是一樣?
只好拜訪一下估狗大神了。

OLE error 800A03EC - Toolbox for IT Groups

隨便看了一下,
感覺應該是要利用 OLE 轉資料到 EXCEL 的時候出現錯誤,
恩~~~看到這邊,決定把 EXCEL 關起來再跑報表看看,
果然就可以了,筆記一下。

實驗證明,應該是 EXCEL 再輸入的狀態下是沒辦法轉出 EXCEL 的,
所以只要不是在輸入狀態下就可以轉出了,不用關閉所有的 EXCEL ,以上。

2014年6月12日 星期四

Oracle - 找出壞掉的物件重新 compile


最近在交易檔加了一個欄位,然後一干人等全部都壞掉了,
因為壞掉的有一狗票,所以不太可能一個、一個慢慢去把它修好,
所以找了一下,寫成以下偷懶寫法:

SELECT 'ALTER ' || DECODE(SUBSTR(OBJECT_TYPE, 1, 7), 'PACKAGE', ' PACKAGE', OBJECT_TYPE) 
       || ' ' || OBJECT_NAME || ' COMPILE' 
       || DECODE(SUBSTR(OBJECT_TYPE, 1, 7), 'PACKAGE', ' PACKAGE;', ';')
FROM USER_OBJECTS
WHERE OBJECT_TYPE IN ('FUNCTION', 'PROCEDURE', 'PACKAGE', 'PACKAGE BODY')
      AND STATUS = 'INVALID';

簡單的說就是透過 USER_OBJECTS 這個資料表的 STATUS 來找出壞掉的物件,
要注意的是 PACKAGE 的 OBJECT_TYPE 會分成 PACKAGE 跟 PACKAGE BODY 這兩個,
所以要特別處理一下。

參考一下 ALTER PACKAGE

可以針對 PACKAGE BODY Recompile ,可能有省一點工吧?

ALTER PACKAGE hr.emp_mgmt COMPILE BODY; 

不過我想我還是直接對整個 PACKAGE Compile 吧!

ALTER PACKAGE emp_mgmt COMPILE PACKAGE;

我想等等阿輝應該會解釋一下兩者的差異,
我是看了半天看不出來,不知道是英文不好?還是他沒解釋?
阿輝換你了!(啪)


2014年6月6日 星期五

Oracle - 如何在 CURSOR 裡面直接更新該筆資料


正所謂一懶還有一懶懶,
每次看到同事寫的程式裡面有一點是我覺得很奇怪的,
明明我就是抓某個 TABLE 裡面的某些資料出來,
為什麼在 FOR LOOP 裡面要更新那一筆資料的時候,
卻還是下 UPDATE 該 TABLE 然後一堆條件呢?

所以今天在寫個 FUNC 的時候就想說來找一下,
應該會有比較偷懶聰明的寫法吧!
找到了下面這個說明
[Chapter 6] 6.11 SELECT FOR UPDATE in Cursors
看起來應該可以,試了一下,
挑了一種我覺得比較偷懶簡潔的寫法,如下:

   CURSOR CUR_TEST IS
      SELECT *
      FROM TB_TEST
      FOR UPDATE;

只要在 CURSOR 最後面加上 FOR UPDATE 就可以了,很簡單。
然後 FOR LOOP 裡面的寫法也很簡單,如下:

   FOR REC_TEST IN CUR_TEST
   LOOP
      
      UPDATE TB_TEST
      SET CALC_AMT = 10000000 
      WHERE CURRENT OF CUR_TEST;

   END LOOP;

UPDATE 甚麼不是重點,
重點是 WHERE 條件的寫法 CURRENT OF CUR_TEST 就可以了,
夠簡單,讚!

進步始終來自於惰性!共勉之~~~

2014年5月6日 星期二

Oracle - Right Str ?

我真是個不認真記語法的人,
每次都很自然地寫出  RIGHT('ABCD', 2) 這種神人級的語法,
就我要從右邊取出 CD 咩!

剛剛找了一下,發現有個寫法還不錯,

SUBSTR('ABCD', -2, 2)

第二個參數可以應該可以解讀為從右邊數來第二個開始。
(自我解讀 XD)

所以如果我想取得 BC 可以用下面的寫法

SUBSTR('ABCD', -3, 2)

不過這樣的需求應該是比較少才對。
(自己為 :P)