回答ではありません
phpでもVB.NETでもなく、dockerが動作するLinux上python3で書かれた、ORMであるSQLAlchemyとデータ解析支援ライブラリのpandasを使用した実験コード(shell script)を置いておきます。想定DBはSQL Serverではなく、sqlite3/mysql/postgresqlの3つです。
空のディレクトリで実行すると、dockerを使用してデータベースを構築し、ITEM_MASTERテーブルを作成、中に2つだけレコードを作って、その中身をcsvにダンプしています。ダンプしている部分だけのコード(shell scriptの実行で生成されるdump_csv_sqlite3.py)であれば、
python
1from sqlalchemy import create_engine
2from sqlalchemy.orm import Session
3from sqlalchemy.ext.automap import automap_base
4import pandas as pd
5DATABASE = 'sqlite:///db.sqlite3'
6Base = automap_base()
7engine = create_engine(
8 DATABASE,
9 echo=True
10)
11Base.prepare(engine, reflect=True)
12ItemMaster = Base.classes.ITEM_MASTER
13with Session(engine) as session:
14 query = session.query(ItemMaster)
15 df = pd.read_sql(str(query), session.bind)
16 df.to_csv('data_sqlite3.csv',index=False)
これだけですよ(コード上ITEM_MASTER
が商品マスタのテーブル名)。ちゃんと正しくエスケープされたCSVを吐くと思いますし、HTML部分はそのカラムの型に応じて最良の方法で出力されると思います。.xlsxで吐くようなことも簡単な変更で出来るでしょう。大量のデータをそのまま扱うことはできないかもしれませんが、検討される上で、普通どうするんだろう?というような部分は、ある程度参考になるかもしれません。
一応言っておくと、よく分からないのに本番環境で使う、というのは絶対やめましょう。業務でそんなことをしたら怒られるだけではすみません(クビが飛ぶ上に場合によっては損害賠償請求されます)。
bash
1set -eux
2if [ -d env ]; then
3 . env/bin/activate
4else
5 python3 -m venv env
6 . env/bin/activate
7 pip install -U pip setuptools
8 pip install SQLAlchemy pandas mysql-connector-python psycopg2-binary
9fi
10DB_ROOT_PASSWORD=my-secret-pw
11cat >start_mysql.sh <<EOF
12docker run -d --rm --name mysql -v $(pwd)/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=$DB_ROOT_PASSWORD -p 3306:3306 mysql
13docker exec -i mysql bash <<EOF2
14while ! mysql -uroot -p"$DB_ROOT_PASSWORD" </dev/null 2>/dev/null;do
15 sleep 1
16done
17EOF2
18EOF
19cat >start_postgres.sh <<EOF
20docker run -d --rm --name postgres -v $(pwd)/postgres:/var/lib/postgresql/data -e POSTGRES_PASSWORD=$DB_ROOT_PASSWORD -p 5432:5432 postgres
21docker exec -i postgres bash <<EOF2
22while ! psql --username postgres </dev/null 2>/dev/null;do
23 sleep 1
24done
25EOF
26cat >stop_mysql.sh <<EOF
27docker stop mysql
28EOF
29cat >stop_postgres.sh <<EOF
30docker stop postgres
31EOF
32for db in sqlite3 mysql postgres; do
33 case $db in
34 sqlite3)
35 constr='sqlite:///db.sqlite3'
36 ;;
37 mysql)
38 constr="mysql+mysqlconnector://root:${DB_ROOT_PASSWORD}@localhost/mysql"
39 ;;
40 postgres)
41 constr="postgresql://postgres:${DB_ROOT_PASSWORD}@localhost/postgres"
42 ;;
43 esac
44 cat >create_data_$db.py <<EOF
45from sqlalchemy import create_engine, Column, Integer, BigInteger, String, Numeric, UnicodeText
46from sqlalchemy.orm import DeclarativeBase,sessionmaker
47class Base(DeclarativeBase):
48 pass
49"""
50商品マスタ
51"""
52class ItemMaster(Base):
53 __tablename__ = 'ITEM_MASTER'
54 item_id = Column('item_id', Integer, primary_key=True, autoincrement=True, comment='商品ID') # sqlite3でautoincrementにするにはIntegerにする必要がある
55 jan_code = Column('jan_code', String(13), comment='JANコード', nullable=True)
56 isbn_code = Column('isbn_code', String(13), comment='ISBNコード', nullable=True)
57 model_number = Column('model_number', String(100), comment='型番', nullable=True)
58 item_name = Column('item_name', String(100), comment='商品名')
59 purchase_price = Column('purchase_price', Numeric(20,2), comment='仕入価格')
60 purchase_lot_id = Column('purchase_lot_id', BigInteger, comment='購入ロットID', default=0)
61 supplier_id = Column('supplier_id', BigInteger, comment='サプライヤーID', default=0)
62 lead_time_id = Column('lead_time_id', BigInteger, comment='リードタイムID', default=0)
63 sales_channel_id = Column('sales_channel_id', BigInteger, comment='販売チャンネルID', default=0)
64 html_code = Column('html_code', UnicodeText(), comment='HTMLコード', default=0)
65DATABASE = '$constr'
66engine = create_engine(
67 DATABASE,
68 echo=True
69)
70Base.metadata.create_all(engine)
71Session = sessionmaker(
72 autocommit = False,
73 autoflush = False,
74 bind = engine
75)
76with Session.begin() as session:
77 item = ItemMaster()
78 item.jan_code = '4901990028929'
79 item.item_name = 'やきそば弁当'
80 item.purchase_price = 100.00
81 # https://www.maruchan.co.jp/products/search/205405.html より引用
82 item.html_code = '''\
83<table><tbody>
84<tr><th>希望小売価格</th> <td>236 円(税抜価格)</td></tr>
85<tr><th>内容量</th> <td>132g(めん100g)</td></tr>
86<tr><th>リニューアル日</th><td>2019年02月04日</td></tr>
87<tr><th>JANコード</th> <td>4901990028929</td></tr>
88<tr><th>販売エリア</th> <td>北海道</td></tr>
89</tbody></table>
90'''
91 session.add(item)
92 item = ItemMaster()
93 item.isbn_code = '9780141354828'
94 item.item_name = 'Charlotte\'s Web'
95 item.purchase_price = 1442.00
96 # https://www.amazon.co.jp/Charlottes-Web-Puffin-Book-White/dp/0141354828/ より引用
97 item.html_code = '''\
98<p><span>'From grammar to the tenderness in which this story is delivered, E. B. White's writing is so perfect...
99And Garth William's muted illustrations are entirely without fault. Whether read aloud or solo, this is a book well deserving of it's "classic" status.' - </span>
100<span class="a-text-italic">The Children's Book Review</span>
101<span><br><br>A poignant, humorous story of a pig, a spider and a little girl.<br>
102Wilbur the pig's life has already been saved by Fern, but when he is sold to her uncle, he realises his life is in even more danger.
103Enter Charlotte A. Cavatica, a beautiful large grey spider. Charlotte is determined to keep Wilbur from the chopping block,
104and comes up with an ingenious way to do just that.</span></p>\
105'''
106 session.add(item)
107 session.commit()
108EOF
109 cat >dump_csv_$db.py <<EOF
110from sqlalchemy import create_engine
111from sqlalchemy.orm import Session
112from sqlalchemy.ext.automap import automap_base
113import pandas as pd
114DATABASE = '$constr'
115Base = automap_base()
116engine = create_engine(
117 DATABASE,
118 echo=True
119)
120Base.prepare(engine, reflect=True)
121ItemMaster = Base.classes.ITEM_MASTER
122with Session(engine) as session:
123 query = session.query(ItemMaster)
124 df = pd.read_sql(str(query), session.bind)
125 df.to_csv('data_$db.csv',index=False)
126EOF
127 if [ -f start_$db.sh ]; then sh -eux start_$db.sh;fi
128 python create_data_$db.py
129 python dump_csv_$db.py
130 if [ -f stop_$db.sh ]; then sh -eux stop_$db.sh;fi
131done
132deactivate
あと、最後になってしまいましたが、SQL Serverであれば付属のコマンドであるbcpでcsvを扱えたと思います。できることは限られますが、速度も申し分ないはずですよ。