參考(1)
參考(2)
---
(1)
Windows印表機分享
建議你在client端用setup印表機的方式安裝,再設定連接埠,比較不會出問題
(選Local port->連接埠名稱 //xxx.xxx.xxx.xxx/???????
也就是//PC的IP/分享的印表機名稱,ip的確認方式:在程式集/附屬應用程式/命令提示字元 輸入ipconfig即可看到你網卡的ip)
原因在於用直接分享的方式連,雖然很方便,但是有可能會造成client端印表機驅動程式功能不全,造成不可預期的列印問題
(2)
原來不要直接在網路分享上點分享的印表機安裝
而是要在要使用的CLIENT端先安裝printer driver
"開始"->"設定"->"印表機及傳真"->選該印表機右鍵按"內容"
->"連接埠"->新增連接埠"->選"Local Port"->"新增連接埠"->
跳出一個小視窗輸入你要使用的印表機
例如: //ip_or_username/printer_name
----------------------------------------------------------------
以上是參考,底下為我的實際作法
A.先在要開分享的PC上接好印表機並安裝驅動程式後;並開分享
B.Cleint 端,安裝方式:*重點在此* (並準備好印表機驅動程式)
2011年11月30日 星期三
2011年11月29日 星期二
分頁~資料數~限定每頁細項顯示資料數
參考來源
------
2-4 . 公式解說 :
CrystalReport 函數運用 : 函數分類 --> 列印狀態 -->
OnLastRecord : 判斷目前資料是否顯示到最後一筆,並回傳 True 或是 False 。
RecordNumber : 記錄目前顯示的資料數,由 1~~N。
函數分類 --> 程式捷徑 -->
IIF (運算式,當運算為 True ,當運算式為 False )
函數分類 --> 運算子 -->
mod :
公式 :
IIF (OnLastRecord ,false ,if RecordNumber mod 20 = 0 then true else false );
判斷當 OnLastRecord = True ,表示最後一筆資料,就停止分頁。
判斷當 OnLastRecord = False ,就去計算 目前資料數 RecordNumber mod 20 是否等於 0 。
等於 0 表示繼續分頁,不等於 0 表示不分頁。
------
2-4 . 公式解說 :
CrystalReport 函數運用 : 函數分類 --> 列印狀態 -->
OnLastRecord : 判斷目前資料是否顯示到最後一筆,並回傳 True 或是 False 。
RecordNumber : 記錄目前顯示的資料數,由 1~~N。
函數分類 --> 程式捷徑 -->
IIF (運算式,當運算為 True ,當運算式為 False )
函數分類 --> 運算子 -->
mod :
公式 :
IIF (OnLastRecord ,false ,if RecordNumber mod 20 = 0 then true else false );
判斷當 OnLastRecord = True ,表示最後一筆資料,就停止分頁。
判斷當 OnLastRecord = False ,就去計算 目前資料數 RecordNumber mod 20 是否等於 0 。
等於 0 表示繼續分頁,不等於 0 表示不分頁。
2011年11月28日 星期一
公式(1)
if {EnterLog.out_tim}=#1900/1/1 12:00:00# then formula="無資料" end if
If dEnd = "" Then Formula = (a.startdate-a.enddate) * count*unitprice Else Formula = dStart*count*unitprice
End
2011年11月27日 星期日
2011年11月25日 星期五
無法序列化 datatable
---
真是神奇,就是查不出差異性在哪
相同code , 不同模組而已;一邊可以,另一個卻不行..Orz
不得已,只好將datatable writexml , 改為:dataset writexml (即可序列化 xml )
如何用 C# 撰寫序列化(Serialize)與反序列化(Deserialize)
參考引用:
--
1. 序列化(Serialize):將一個物件實體轉換成 XML 格式
public static string SpecificationDataTableSerialize(dsSpecifications.SpecificationDataTable dt)
{
System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(dt.GetType());
StringBuilder sb = new StringBuilder();
System.IO.StringWriter writer = new System.IO.StringWriter(sb);
ser.Serialize(writer, dt);
return sb.ToString();
}
2. 反序列化(Deserialize):將一個 XML 文件轉成物件實體
public static dsSpecifications.SpecificationDataTable SpecificationDataTableDeserialize(string s)
{
dsSpecifications.SpecificationDataTable dt = new dsSpecifications.SpecificationDataTable();
// 如果傳入的 s 字串不是有效的 XML 格式的話,會發生 Exception,記得要做好 Error Handling
System.Xml.XmlDocument xdoc = new System.Xml.XmlDocument();
xdoc.LoadXml(s);
System.Xml.XmlNodeReader reader = new System.Xml.XmlNodeReader(xdoc.DocumentElement);
System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(dt.GetType());
object obj = ser.Deserialize(reader);
return obj as dsSpecifications.SpecificationDataTable;
}
--
1. 序列化(Serialize):將一個物件實體轉換成 XML 格式
public static string SpecificationDataTableSerialize(dsSpecifications.SpecificationDataTable dt)
{
System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(dt.GetType());
StringBuilder sb = new StringBuilder();
System.IO.StringWriter writer = new System.IO.StringWriter(sb);
ser.Serialize(writer, dt);
return sb.ToString();
}
2. 反序列化(Deserialize):將一個 XML 文件轉成物件實體
public static dsSpecifications.SpecificationDataTable SpecificationDataTableDeserialize(string s)
{
dsSpecifications.SpecificationDataTable dt = new dsSpecifications.SpecificationDataTable();
// 如果傳入的 s 字串不是有效的 XML 格式的話,會發生 Exception,記得要做好 Error Handling
System.Xml.XmlDocument xdoc = new System.Xml.XmlDocument();
xdoc.LoadXml(s);
System.Xml.XmlNodeReader reader = new System.Xml.XmlNodeReader(xdoc.DocumentElement);
System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(dt.GetType());
object obj = ser.Deserialize(reader);
return obj as dsSpecifications.SpecificationDataTable;
}
DataTable的序列化和反序列化
///
/// 序列化DataTable
///
/// DataTable
/// 序列化的DataTable
private static string SerializeDataTableXml(DataTable pDt) {
// 序列化DataTable
StringBuilder sb = new StringBuilder();
XmlWriter writer = XmlWriter.Create(sb);
XmlSerializer serializer = new XmlSerializer(typeof(DataTable));
serializer.Serialize(writer, pDt);
writer.Close();
return sb.ToString();
}
///
/// 反序列化DataTable
///
/// 序列化的DataTable
/// DataTable
public static DataTable DeserializeDataTable(string pXml) {
StringReader strReader = new StringReader(pXml);
XmlReader xmlReader = XmlReader.Create(strReader);
XmlSerializer serializer = new XmlSerializer(typeof(DataTable));
DataTable dt = serializer.Deserialize(xmlReader) as DataTable;
return dt;
}
直接將word檔送至印表機
參考引用
--
mports Microsoft.Office.Interop
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Dim wod_app As New Word.Application '這邊要注意建立app時要用new
Dim wod_doc As New Word.Document
wod_doc = wod_app.Documents.Open("c:\1.doc", , True)
wod_app.ActiveDocument.SaveAs("c:\" & i & ".doc")
' wod_app.Visible = True '預覽列印
wod_app.PrintOut(Copies:=1) '直接列印預設印表機
wod_app.Quit()
End Sub
--
mports Microsoft.Office.Interop
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Dim wod_app As New Word.Application '這邊要注意建立app時要用new
Dim wod_doc As New Word.Document
wod_doc = wod_app.Documents.Open("c:\1.doc", , True)
wod_app.ActiveDocument.SaveAs("c:\" & i & ".doc")
' wod_app.Visible = True '預覽列印
wod_app.PrintOut(Copies:=1) '直接列印預設印表機
wod_app.Quit()
End Sub
设置打印机纸张大小
參考引用:
--
using System.Drawing.Printing.PrintDocument
using System.Drawing.Printing.PrinterSettings.PaperSizeCollection
using System.Drawing.Printing.PaperSize
using System.Drawing.Printing.PageSettings
/////////需要以上引用
PrintDocument pd = new PrintDocument();
PaperSize p=null;
foreach(PaperSize ps in pd.PrinterSettings.PaperSizes)
{ if(ps.PaperName.Equals("A3"))
p = ps;
}
pd.DefaultPageSettings.PaperSize = p;
pd.Print();
指定:
pd.DefaultPageSettings.PaperSize = new PaperSize("自定义名称",宽,长)
--
using System.Drawing.Printing.PrintDocument
using System.Drawing.Printing.PrinterSettings.PaperSizeCollection
using System.Drawing.Printing.PaperSize
using System.Drawing.Printing.PageSettings
/////////需要以上引用
PrintDocument pd = new PrintDocument();
PaperSize p=null;
foreach(PaperSize ps in pd.PrinterSettings.PaperSizes)
{ if(ps.PaperName.Equals("A3"))
p = ps;
}
pd.DefaultPageSettings.PaperSize = p;
pd.Print();
指定:
pd.DefaultPageSettings.PaperSize = new PaperSize("自定义名称",宽,长)
2011年11月24日 星期四
自己设计的一个printpreview程序
參考引用
--
自己设计的一个printpreview程序,最大的特点是把页面设置,打印设置,字体设置整合到一个窗口中了。还有很多问题,希望高手指点一二。
源代码:
Imports System.Drawing.printing
Imports System.io
Public Class previewcontrol
Inherits System.Windows.Forms.Form
#Region " Windows 窗体设计器生成的代码 "
Public Sub New()
MyBase.New()
'该调用是 Windows 窗体设计器所必需的。
InitializeComponent()
'在 InitializeComponent() 调用之后添加任何初始化
End Sub
'窗体重写 dispose 以清理组件列表。
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Windows 窗体设计器所必需的
Private components As System.ComponentModel.IContainer
'注意: 以下过程是 Windows 窗体设计器所必需的
'可以使用 Windows 窗体设计器修改此过程。
'不要使用代码编辑器修改它。
Friend WithEvents PrintPreviewControl1 As System.Windows.Forms.PrintPreviewControl
Friend WithEvents printsetup As dbcbutton.dbcbutton
Private WithEvents pagesetup As dbcbutton.dbcbutton
Friend WithEvents Label1 As System.Windows.Forms.Label
Friend WithEvents Label2 As System.Windows.Forms.Label
Friend WithEvents Label3 As System.Windows.Forms.Label
Friend WithEvents openfile As dbcbutton.dbcbutton
Friend WithEvents setfont As dbcbutton.dbcbutton
Friend WithEvents printthis As dbcbutton.dbcbutton
Friend WithEvents pagecount As System.Windows.Forms.NumericUpDown
Friend WithEvents pageroom As System.Windows.Forms.ComboBox
Private Sub InitializeComponent()
Me.PrintPreviewControl1 = New System.Windows.Forms.PrintPreviewControl
Me.printsetup = New dbcbutton.dbcbutton
Me.pagesetup = New dbcbutton.dbcbutton
Me.pagecount = New System.Windows.Forms.NumericUpDown
Me.pageroom = New System.Windows.Forms.ComboBox
Me.Label1 = New System.Windows.Forms.Label
Me.Label2 = New System.Windows.Forms.Label
Me.Label3 = New System.Windows.Forms.Label
Me.openfile = New dbcbutton.dbcbutton
Me.setfont = New dbcbutton.dbcbutton
Me.printthis = New dbcbutton.dbcbutton
CType(Me.pagecount, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
'PrintPreviewControl1
'
Me.PrintPreviewControl1.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
Or System.Windows.Forms.AnchorStyles.Left) _
Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
Me.PrintPreviewControl1.AutoZoom = False
Me.PrintPreviewControl1.Location = New System.Drawing.Point(8, 40)
Me.PrintPreviewControl1.Name = "PrintPreviewControl1"
Me.PrintPreviewControl1.Size = New System.Drawing.Size(696, 280)
Me.PrintPreviewControl1.TabIndex = 0
Me.PrintPreviewControl1.Zoom = 0.3
'
'printsetup
'
Me.printsetup.BackColor = System.Drawing.SystemColors.Control
Me.printsetup.ButtonStyle = dbcbutton.dbcbutton.Style.RectStyle
Me.printsetup.GrayColor = System.Drawing.Color.BurlyWood
Me.printsetup.LightColor = System.Drawing.Color.White
Me.printsetup.Location = New System.Drawing.Point(168, 8)
Me.printsetup.mytext = "打印设置"
Me.printsetup.Name = "printsetup"
Me.printsetup.Size = New System.Drawing.Size(72, 24)
Me.printsetup.TabIndex = 1
'
'pagesetup
'
Me.pagesetup.BackColor = System.Drawing.SystemColors.Control
Me.pagesetup.ButtonStyle = dbcbutton.dbcbutton.Style.RectStyle
Me.pagesetup.GrayColor = System.Drawing.Color.BurlyWood
Me.pagesetup.LightColor = System.Drawing.Color.White
Me.pagesetup.Location = New System.Drawing.Point(256, 8)
Me.pagesetup.mytext = "页面设置"
Me.pagesetup.Name = "pagesetup"
Me.pagesetup.Size = New System.Drawing.Size(72, 24)
Me.pagesetup.TabIndex = 2
'
'pagecount
'
Me.pagecount.Location = New System.Drawing.Point(624, 11)
Me.pagecount.Minimum = New Decimal(New Integer() {1, 0, 0, 0})
Me.pagecount.Name = "pagecount"
Me.pagecount.Size = New System.Drawing.Size(40, 21)
Me.pagecount.TabIndex = 3
Me.pagecount.Value = New Decimal(New Integer() {1, 0, 0, 0})
'
'pageroom
'
Me.pageroom.Items.AddRange(New Object() {"25%", "50%", "75%", "100%"})
Me.pageroom.Location = New System.Drawing.Point(512, 12)
Me.pageroom.Name = "pageroom"
Me.pageroom.Size = New System.Drawing.Size(56, 20)
Me.pageroom.TabIndex = 4
Me.pageroom.Text = "缩放"
'
'Label1
'
Me.Label1.Location = New System.Drawing.Point(456, 16)
Me.Label1.Name = "Label1"
Me.Label1.Size = New System.Drawing.Size(48, 16)
Me.Label1.TabIndex = 5
Me.Label1.Text = "缩放:"
Me.Label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
'
'Label2
'
Me.Label2.Location = New System.Drawing.Point(584, 16)
Me.Label2.Name = "Label2"
Me.Label2.Size = New System.Drawing.Size(32, 16)
Me.Label2.TabIndex = 6
Me.Label2.Text = "第"
Me.Label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
'
'Label3
'
Me.Label3.Location = New System.Drawing.Point(672, 16)
Me.Label3.Name = "Label3"
Me.Label3.Size = New System.Drawing.Size(32, 16)
Me.Label3.TabIndex = 7
Me.Label3.Text = "页"
Me.Label3.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
'
'openfile
'
Me.openfile.BackColor = System.Drawing.SystemColors.Control
Me.openfile.ButtonStyle = dbcbutton.dbcbutton.Style.RectStyle
Me.openfile.GrayColor = System.Drawing.Color.BurlyWood
Me.openfile.LightColor = System.Drawing.Color.White
Me.openfile.Location = New System.Drawing.Point(8, 8)
Me.openfile.mytext = "选择文件"
Me.openfile.Name = "openfile"
Me.openfile.Size = New System.Drawing.Size(72, 24)
Me.openfile.TabIndex = 8
'
'setfont
'
Me.setfont.BackColor = System.Drawing.SystemColors.Control
Me.setfont.ButtonStyle = dbcbutton.dbcbutton.Style.RectStyle
Me.setfont.GrayColor = System.Drawing.Color.BurlyWood
Me.setfont.LightColor = System.Drawing.Color.White
Me.setfont.Location = New System.Drawing.Point(88, 8)
Me.setfont.mytext = "设置字体"
Me.setfont.Name = "setfont"
Me.setfont.Size = New System.Drawing.Size(72, 24)
Me.setfont.TabIndex = 9
'
'printthis
'
Me.printthis.BackColor = System.Drawing.SystemColors.Control
Me.printthis.ButtonStyle = dbcbutton.dbcbutton.Style.RectStyle
Me.printthis.GrayColor = System.Drawing.Color.BurlyWood
Me.printthis.LightColor = System.Drawing.Color.White
Me.printthis.Location = New System.Drawing.Point(344, 8)
Me.printthis.mytext = "开始打印"
Me.printthis.Name = "printthis"
Me.printthis.Size = New System.Drawing.Size(72, 24)
Me.printthis.TabIndex = 10
'
'previewcontrol
'
Me.AutoScaleBaseSize = New System.Drawing.Size(6, 14)
Me.ClientSize = New System.Drawing.Size(712, 325)
Me.Controls.Add(Me.printthis)
Me.Controls.Add(Me.setfont)
Me.Controls.Add(Me.openfile)
Me.Controls.Add(Me.Label3)
Me.Controls.Add(Me.Label2)
Me.Controls.Add(Me.Label1)
Me.Controls.Add(Me.pageroom)
Me.Controls.Add(Me.pagecount)
Me.Controls.Add(Me.pagesetup)
Me.Controls.Add(Me.printsetup)
Me.Controls.Add(Me.PrintPreviewControl1)
Me.Name = "previewcontrol"
Me.Text = "previewcontrol"
CType(Me.pagecount, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
End Sub
#End Region
Private printstream As StreamReader
Private printfont As Font
Dim newprintdocument As New PrintDocument
Private totalpage As Single = 0 '存放总页数
Private Sub previewcontrol_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
AddHandler newprintdocument.PrintPage, AddressOf newprintdocument_printpage
End Sub
'页面的printpage函数
Private Sub newprintdocument_printpage(ByVal sender As Object, ByVal ev As PrintPageEventArgs)
Try
totalpage += 1
If printstream.ReadLine Is Nothing Then
MsgBox("无内容")
Exit Sub
End If
If printfont Is Nothing Then
printfont = New Font("宋体", 12)
End If
Dim pagelines As Single '存放每页可打印的行数
Dim lineheight As Single = printfont.GetHeight(ev.Graphics) '存放行高
Dim xpos As Single = 0 '存放每行打印的X坐标
Dim ypos As Single = 0 '存放每行打印的Y坐标
Dim linecount As Single = 0 '存放已经打印的行数
Dim strformat As New StringFormat
Dim left As Single = ev.MarginBounds.Left
Dim top As Single = ev.MarginBounds.Top
strformat.FormatFlags = StringFormatFlags.LineLimit
Dim printbrush As Brush
printbrush = New SolidBrush(Color.Black)
pagelines = ev.MarginBounds.Height / lineheight
Dim strline As String = Nothing
Do While linecount < pagelines
strline = printstream.ReadLine
If strline Is Nothing Then
Exit Do
End If
top = ev.MarginBounds.Top + linecount * lineheight
ev.Graphics.DrawString(strline, printfont, printbrush, left, top, strformat)
linecount = linecount + 1
Loop
If strline Is Nothing Then
ev.HasMorePages = False
Else
ev.HasMorePages = True
End If
Catch ex As Printing.InvalidPrinterException
MsgBox(ex.Message, MsgBoxStyle.OKOnly, "打印出错")
MsgBox(ex.Source)
Catch ex1 As Exception
MsgBox(ex1.Message)
MsgBox(ex1.Source)
End Try
pagecount.Maximum = totalpage
pagecount.Minimum = 1
End Sub
'打开文件,读取文件流,开始填充打印页面
Private Sub openfile_onclick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles openfile.Click
totalpage = 0
If Not (printstream Is Nothing) Then
printstream.Close()
End If
Dim filedialog As New OpenFileDialog
If filedialog.ShowDialog = DialogResult.OK Then
printstream = New StreamReader(filedialog.FileName)
PrintPreviewControl1.Document = newprintdocument
PrintPreviewControl1.Zoom = 1
End If
End Sub
'字体设置对话框
Private Sub setfont_onclick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles setfont.Click
Dim setfontdialog As New FontDialog
If setfontdialog.ShowDialog = DialogResult.OK Then
totalpage = 0
printstream.BaseStream.Seek(0, SeekOrigin.Begin)
printfont = setfontdialog.Font
PrintPreviewControl1.InvalidatePreview()
Me.Refresh()
End If
End Sub
'打印设置对话框
Private Sub printsetup_onclick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles printsetup.Click
Dim printsetup As New PrintDialog
printsetup.Document = newprintdocument
If printsetup.ShowDialog = DialogResult.OK Then
totalpage = 0
printstream.BaseStream.Seek(0, SeekOrigin.Begin)
PrintPreviewControl1.InvalidatePreview()
Me.Refresh()
End If
End Sub
'页面设置对话框
Private Sub pagesetup_onclick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles pagesetup.Click
Dim pagesetup As New PageSetupDialog
pagesetup.Document = newprintdocument
If pagesetup.ShowDialog = DialogResult.OK Then
totalpage = 0
printstream.BaseStream.Seek(0, SeekOrigin.Begin)
PrintPreviewControl1.InvalidatePreview()
Me.Refresh()
End If
End Sub
'打印文档
Private Sub printthis_onclick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles printthis.Click
newprintdocument.Print()
End Sub
'当窗口关闭时关闭文档流
Private Sub previewcontrol_onclose(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Closed
If Not (printstream Is Nothing) Then
printstream.Close()
End If
End Sub
'改变当前显示的页面
Private Sub NumericUpDown1_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles pagecount.ValueChanged
PrintPreviewControl1.StartPage = pagecount.Value - 1
End Sub
'改变显示比例
Private Sub pageroom_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles pageroom.SelectedIndexChanged
Select Case pageroom.Items(pageroom.SelectedIndex)
Case "25%"
PrintPreviewControl1.Zoom = 0.25
PrintPreviewControl1.Refresh()
Me.Refresh()
Case "50%"
PrintPreviewControl1.Zoom = 0.5
PrintPreviewControl1.Refresh()
Me.Refresh()
Case "75%"
PrintPreviewControl1.Zoom = 0.75
PrintPreviewControl1.Refresh()
Me.Refresh()
Case "100%"
PrintPreviewControl1.Zoom = 1
PrintPreviewControl1.Refresh()
Me.Refresh()
End Select
End Sub
End Class
--
自己设计的一个printpreview程序,最大的特点是把页面设置,打印设置,字体设置整合到一个窗口中了。还有很多问题,希望高手指点一二。
源代码:
Imports System.Drawing.printing
Imports System.io
Public Class previewcontrol
Inherits System.Windows.Forms.Form
#Region " Windows 窗体设计器生成的代码 "
Public Sub New()
MyBase.New()
'该调用是 Windows 窗体设计器所必需的。
InitializeComponent()
'在 InitializeComponent() 调用之后添加任何初始化
End Sub
'窗体重写 dispose 以清理组件列表。
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Windows 窗体设计器所必需的
Private components As System.ComponentModel.IContainer
'注意: 以下过程是 Windows 窗体设计器所必需的
'可以使用 Windows 窗体设计器修改此过程。
'不要使用代码编辑器修改它。
Friend WithEvents PrintPreviewControl1 As System.Windows.Forms.PrintPreviewControl
Friend WithEvents printsetup As dbcbutton.dbcbutton
Private WithEvents pagesetup As dbcbutton.dbcbutton
Friend WithEvents Label1 As System.Windows.Forms.Label
Friend WithEvents Label2 As System.Windows.Forms.Label
Friend WithEvents Label3 As System.Windows.Forms.Label
Friend WithEvents openfile As dbcbutton.dbcbutton
Friend WithEvents setfont As dbcbutton.dbcbutton
Friend WithEvents printthis As dbcbutton.dbcbutton
Friend WithEvents pagecount As System.Windows.Forms.NumericUpDown
Friend WithEvents pageroom As System.Windows.Forms.ComboBox
Me.PrintPreviewControl1 = New System.Windows.Forms.PrintPreviewControl
Me.printsetup = New dbcbutton.dbcbutton
Me.pagesetup = New dbcbutton.dbcbutton
Me.pagecount = New System.Windows.Forms.NumericUpDown
Me.pageroom = New System.Windows.Forms.ComboBox
Me.Label1 = New System.Windows.Forms.Label
Me.Label2 = New System.Windows.Forms.Label
Me.Label3 = New System.Windows.Forms.Label
Me.openfile = New dbcbutton.dbcbutton
Me.setfont = New dbcbutton.dbcbutton
Me.printthis = New dbcbutton.dbcbutton
CType(Me.pagecount, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
'PrintPreviewControl1
'
Me.PrintPreviewControl1.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
Or System.Windows.Forms.AnchorStyles.Left) _
Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
Me.PrintPreviewControl1.AutoZoom = False
Me.PrintPreviewControl1.Location = New System.Drawing.Point(8, 40)
Me.PrintPreviewControl1.Name = "PrintPreviewControl1"
Me.PrintPreviewControl1.Size = New System.Drawing.Size(696, 280)
Me.PrintPreviewControl1.TabIndex = 0
Me.PrintPreviewControl1.Zoom = 0.3
'
'printsetup
'
Me.printsetup.BackColor = System.Drawing.SystemColors.Control
Me.printsetup.ButtonStyle = dbcbutton.dbcbutton.Style.RectStyle
Me.printsetup.GrayColor = System.Drawing.Color.BurlyWood
Me.printsetup.LightColor = System.Drawing.Color.White
Me.printsetup.Location = New System.Drawing.Point(168, 8)
Me.printsetup.mytext = "打印设置"
Me.printsetup.Name = "printsetup"
Me.printsetup.Size = New System.Drawing.Size(72, 24)
Me.printsetup.TabIndex = 1
'
'pagesetup
'
Me.pagesetup.BackColor = System.Drawing.SystemColors.Control
Me.pagesetup.ButtonStyle = dbcbutton.dbcbutton.Style.RectStyle
Me.pagesetup.GrayColor = System.Drawing.Color.BurlyWood
Me.pagesetup.LightColor = System.Drawing.Color.White
Me.pagesetup.Location = New System.Drawing.Point(256, 8)
Me.pagesetup.mytext = "页面设置"
Me.pagesetup.Name = "pagesetup"
Me.pagesetup.Size = New System.Drawing.Size(72, 24)
Me.pagesetup.TabIndex = 2
'
'pagecount
'
Me.pagecount.Location = New System.Drawing.Point(624, 11)
Me.pagecount.Minimum = New Decimal(New Integer() {1, 0, 0, 0})
Me.pagecount.Name = "pagecount"
Me.pagecount.Size = New System.Drawing.Size(40, 21)
Me.pagecount.TabIndex = 3
Me.pagecount.Value = New Decimal(New Integer() {1, 0, 0, 0})
'
'pageroom
'
Me.pageroom.Items.AddRange(New Object() {"25%", "50%", "75%", "100%"})
Me.pageroom.Location = New System.Drawing.Point(512, 12)
Me.pageroom.Name = "pageroom"
Me.pageroom.Size = New System.Drawing.Size(56, 20)
Me.pageroom.TabIndex = 4
Me.pageroom.Text = "缩放"
'
'Label1
'
Me.Label1.Location = New System.Drawing.Point(456, 16)
Me.Label1.Name = "Label1"
Me.Label1.Size = New System.Drawing.Size(48, 16)
Me.Label1.TabIndex = 5
Me.Label1.Text = "缩放:"
Me.Label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
'
'Label2
'
Me.Label2.Location = New System.Drawing.Point(584, 16)
Me.Label2.Name = "Label2"
Me.Label2.Size = New System.Drawing.Size(32, 16)
Me.Label2.TabIndex = 6
Me.Label2.Text = "第"
Me.Label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
'
'Label3
'
Me.Label3.Location = New System.Drawing.Point(672, 16)
Me.Label3.Name = "Label3"
Me.Label3.Size = New System.Drawing.Size(32, 16)
Me.Label3.TabIndex = 7
Me.Label3.Text = "页"
Me.Label3.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
'
'openfile
'
Me.openfile.BackColor = System.Drawing.SystemColors.Control
Me.openfile.ButtonStyle = dbcbutton.dbcbutton.Style.RectStyle
Me.openfile.GrayColor = System.Drawing.Color.BurlyWood
Me.openfile.LightColor = System.Drawing.Color.White
Me.openfile.Location = New System.Drawing.Point(8, 8)
Me.openfile.mytext = "选择文件"
Me.openfile.Name = "openfile"
Me.openfile.Size = New System.Drawing.Size(72, 24)
Me.openfile.TabIndex = 8
'
'setfont
'
Me.setfont.BackColor = System.Drawing.SystemColors.Control
Me.setfont.ButtonStyle = dbcbutton.dbcbutton.Style.RectStyle
Me.setfont.GrayColor = System.Drawing.Color.BurlyWood
Me.setfont.LightColor = System.Drawing.Color.White
Me.setfont.Location = New System.Drawing.Point(88, 8)
Me.setfont.mytext = "设置字体"
Me.setfont.Name = "setfont"
Me.setfont.Size = New System.Drawing.Size(72, 24)
Me.setfont.TabIndex = 9
'
'printthis
'
Me.printthis.BackColor = System.Drawing.SystemColors.Control
Me.printthis.ButtonStyle = dbcbutton.dbcbutton.Style.RectStyle
Me.printthis.GrayColor = System.Drawing.Color.BurlyWood
Me.printthis.LightColor = System.Drawing.Color.White
Me.printthis.Location = New System.Drawing.Point(344, 8)
Me.printthis.mytext = "开始打印"
Me.printthis.Name = "printthis"
Me.printthis.Size = New System.Drawing.Size(72, 24)
Me.printthis.TabIndex = 10
'
'previewcontrol
'
Me.AutoScaleBaseSize = New System.Drawing.Size(6, 14)
Me.ClientSize = New System.Drawing.Size(712, 325)
Me.Controls.Add(Me.printthis)
Me.Controls.Add(Me.setfont)
Me.Controls.Add(Me.openfile)
Me.Controls.Add(Me.Label3)
Me.Controls.Add(Me.Label2)
Me.Controls.Add(Me.Label1)
Me.Controls.Add(Me.pageroom)
Me.Controls.Add(Me.pagecount)
Me.Controls.Add(Me.pagesetup)
Me.Controls.Add(Me.printsetup)
Me.Controls.Add(Me.PrintPreviewControl1)
Me.Name = "previewcontrol"
Me.Text = "previewcontrol"
CType(Me.pagecount, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
End Sub
#End Region
Private printstream As StreamReader
Private printfont As Font
Dim newprintdocument As New PrintDocument
Private totalpage As Single = 0 '存放总页数
Private Sub previewcontrol_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
AddHandler newprintdocument.PrintPage, AddressOf newprintdocument_printpage
End Sub
'页面的printpage函数
Private Sub newprintdocument_printpage(ByVal sender As Object, ByVal ev As PrintPageEventArgs)
Try
totalpage += 1
If printstream.ReadLine Is Nothing Then
MsgBox("无内容")
Exit Sub
End If
If printfont Is Nothing Then
printfont = New Font("宋体", 12)
End If
Dim pagelines As Single '存放每页可打印的行数
Dim lineheight As Single = printfont.GetHeight(ev.Graphics) '存放行高
Dim xpos As Single = 0 '存放每行打印的X坐标
Dim ypos As Single = 0 '存放每行打印的Y坐标
Dim linecount As Single = 0 '存放已经打印的行数
Dim strformat As New StringFormat
Dim left As Single = ev.MarginBounds.Left
Dim top As Single = ev.MarginBounds.Top
strformat.FormatFlags = StringFormatFlags.LineLimit
Dim printbrush As Brush
printbrush = New SolidBrush(Color.Black)
pagelines = ev.MarginBounds.Height / lineheight
Dim strline As String = Nothing
Do While linecount < pagelines
strline = printstream.ReadLine
If strline Is Nothing Then
Exit Do
End If
top = ev.MarginBounds.Top + linecount * lineheight
ev.Graphics.DrawString(strline, printfont, printbrush, left, top, strformat)
linecount = linecount + 1
Loop
If strline Is Nothing Then
ev.HasMorePages = False
Else
ev.HasMorePages = True
End If
Catch ex As Printing.InvalidPrinterException
MsgBox(ex.Message, MsgBoxStyle.OKOnly, "打印出错")
MsgBox(ex.Source)
Catch ex1 As Exception
MsgBox(ex1.Message)
MsgBox(ex1.Source)
End Try
pagecount.Maximum = totalpage
pagecount.Minimum = 1
End Sub
'打开文件,读取文件流,开始填充打印页面
Private Sub openfile_onclick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles openfile.Click
totalpage = 0
If Not (printstream Is Nothing) Then
printstream.Close()
End If
Dim filedialog As New OpenFileDialog
If filedialog.ShowDialog = DialogResult.OK Then
printstream = New StreamReader(filedialog.FileName)
PrintPreviewControl1.Document = newprintdocument
PrintPreviewControl1.Zoom = 1
End If
End Sub
'字体设置对话框
Private Sub setfont_onclick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles setfont.Click
Dim setfontdialog As New FontDialog
If setfontdialog.ShowDialog = DialogResult.OK Then
totalpage = 0
printstream.BaseStream.Seek(0, SeekOrigin.Begin)
printfont = setfontdialog.Font
PrintPreviewControl1.InvalidatePreview()
Me.Refresh()
End If
End Sub
'打印设置对话框
Private Sub printsetup_onclick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles printsetup.Click
Dim printsetup As New PrintDialog
printsetup.Document = newprintdocument
If printsetup.ShowDialog = DialogResult.OK Then
totalpage = 0
printstream.BaseStream.Seek(0, SeekOrigin.Begin)
PrintPreviewControl1.InvalidatePreview()
Me.Refresh()
End If
End Sub
'页面设置对话框
Private Sub pagesetup_onclick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles pagesetup.Click
Dim pagesetup As New PageSetupDialog
pagesetup.Document = newprintdocument
If pagesetup.ShowDialog = DialogResult.OK Then
totalpage = 0
printstream.BaseStream.Seek(0, SeekOrigin.Begin)
PrintPreviewControl1.InvalidatePreview()
Me.Refresh()
End If
End Sub
'打印文档
Private Sub printthis_onclick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles printthis.Click
newprintdocument.Print()
End Sub
'当窗口关闭时关闭文档流
Private Sub previewcontrol_onclose(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Closed
If Not (printstream Is Nothing) Then
printstream.Close()
End If
End Sub
'改变当前显示的页面
Private Sub NumericUpDown1_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles pagecount.ValueChanged
PrintPreviewControl1.StartPage = pagecount.Value - 1
End Sub
'改变显示比例
Private Sub pageroom_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles pageroom.SelectedIndexChanged
Select Case pageroom.Items(pageroom.SelectedIndex)
Case "25%"
PrintPreviewControl1.Zoom = 0.25
PrintPreviewControl1.Refresh()
Me.Refresh()
Case "50%"
PrintPreviewControl1.Zoom = 0.5
PrintPreviewControl1.Refresh()
Me.Refresh()
Case "75%"
PrintPreviewControl1.Zoom = 0.75
PrintPreviewControl1.Refresh()
Me.Refresh()
Case "100%"
PrintPreviewControl1.Zoom = 1
PrintPreviewControl1.Refresh()
Me.Refresh()
End Select
End Sub
End Class
一般印表機直接列印
參考 引用:
--
Imports System
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Printing
Private WithEvents printdoc As New Printing.PrintDocument
Private Sub printdoc_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles printdoc.PrintPage
Dim g As Graphics = e.Graphics
Dim pen As New Drawing.Pen(Color.Black, 3)
Dim strfont1 As String = "黑体 " 'arial
Dim font As New Font(strfont1, 16, FontStyle.Bold)
g = e.Graphics
'draw page title
g.DrawString( "一般印表機直接列印", font, Brushes.Black, 330, 140)
End Sub
Public Sub printing()
Dim printDlg As New System.Windows.Forms.PrintDialog()
printDlg.Document = printdoc
If printDlg.ShowDialog = DialogResult.OK Then
printdoc.Print()
End If
End Sub
Public Sub print()
printdoc.Print()
End Sub
Public Sub printpreviewer ()
Dim printviewer As New System.Windows.Forms.PrintPreviewDialog()
printviewer.Document = printdoc
printviewer.SetBounds(0, 0, 768, 1024)
printviewer.ShowDialog()
End Sub
--
Imports System
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Printing
Private WithEvents printdoc As New Printing.PrintDocument
Private Sub printdoc_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles printdoc.PrintPage
Dim g As Graphics = e.Graphics
Dim pen As New Drawing.Pen(Color.Black, 3)
Dim strfont1 As String = "黑体 " 'arial
Dim font As New Font(strfont1, 16, FontStyle.Bold)
g = e.Graphics
'draw page title
g.DrawString( "一般印表機直接列印", font, Brushes.Black, 330, 140)
End Sub
Public Sub printing()
Dim printDlg As New System.Windows.Forms.PrintDialog()
printDlg.Document = printdoc
If printDlg.ShowDialog = DialogResult.OK Then
printdoc.Print()
End If
End Sub
Public Sub print()
printdoc.Print()
End Sub
Public Sub printpreviewer ()
Dim printviewer As New System.Windows.Forms.PrintPreviewDialog()
printviewer.Document = printdoc
printviewer.SetBounds(0, 0, 768, 1024)
printviewer.ShowDialog()
End Sub
紙之規格尺寸大小
A3~B5尺寸大小
A3:
42 X 29.7公分
長邊 420 mm 短邊 297 mm
A4:
29.7 X 21 X公分
長邊 297 mm 短邊 210 mm
A5:
21 X 14.8公分
長邊 210 mm 短邊 148 mm
B4:
36.4 X 25.7公分
長邊 364 mm 短邊 257 mm
B5:
25.7 X 18.2公分
長邊 257 mm 短邊 182 mm
DirectCast 轉換型態取值
Dim outerid As String = DirectCast(a_list.Rows(i).Cells(5).FindControl("outer_id"), TextBox).Text
Dim sku_id As String = DirectCast(a_list.Rows(i).Cells(0).FindControl("sku_id"), Label).Text
字串轉10進位,16進位
參考:
我自己練習:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim a As String = "1234這78"
Dim b As Char() = a.ToCharArray
Dim intvalue As Integer
Dim hexstr As String
ListBox1.Items.Clear()
For i As Integer = 0 To b.Length - 1
intvalue = Convert.ToInt32(b(i))
hexstr = String.Format("{0:x}", intvalue)
ListBox1.Items.Add(String.Format("值:{0},十進位:{1},十六進位:{2}", b(i).ToString, intvalue, hexstr))
Next
End Sub
End Class
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Console { class Program { static void Main(string[] args) { //假設特定字串如下 string subject = "?? 國文(一) Web Development 網路發展"; char[] charArr = subject.ToCharArray(); for (int counter = 0; counter < charArr.Length; counter++) { int intValue = Convert.ToInt32(charArr[counter]); string strHex = String.Format("{0:X}", intValue); System.Console.WriteLine("字元: {0}, 十進位: {1}, 十六進位: {2}", charArr[counter].ToString(), intValue, strHex); } System.Console.Read(); } } }--
我自己練習:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim a As String = "1234這78"
Dim b As Char() = a.ToCharArray
Dim intvalue As Integer
Dim hexstr As String
ListBox1.Items.Clear()
For i As Integer = 0 To b.Length - 1
intvalue = Convert.ToInt32(b(i))
hexstr = String.Format("{0:x}", intvalue)
ListBox1.Items.Add(String.Format("值:{0},十進位:{1},十六進位:{2}", b(i).ToString, intvalue, hexstr))
Next
End Sub
End Class
2011年11月23日 星期三
2011年11月21日 星期一
2011年11月16日 星期三
VFP 寫一個可執行的EXE
心血來潮對 vfp 要完成一個 windows ap exe ,還真是困難重重呀~
費了九牛二虎之google,才把vfp這完成 ! 倒也是通關後,其他不再是難事了!
希望想學vfp 的人別卡在第一關;就失敗退朝了~
:完成圖
:底下為程式和設定值 config.fpw (請參考此篇)
費了九牛二虎之google,才把vfp這完成 ! 倒也是通關後,其他不再是難事了!
希望想學vfp 的人別卡在第一關;就失敗退朝了~
:完成圖
:底下為程式和設定值 config.fpw (請參考此篇)
MS-SQL 2008 SP2 版本號碼
---
MS-SQL 2008 SP2 的版本編號 10.0.4064
記錄起來!
因公司要我查客戶的MS-SQL 2008 版本時,我竟一時也不知到底編號是多少
只好先丟SP1 去跑,哈~還好, SP 還挺聰明的;會自動判別高低版本
2011年11月14日 星期一
ACCESS IIF 的用法
在access 用iif 結果會等於sql case
=IIf([行業別]=1,"烘焙業",IIf([行業別]=2,"餐飲業",IIf([行業別]=3,"咖啡廳",IIf([行業別]=4,"個人工作室",IIf([行業別]=5,"機關團體",IIf([行業別]=6,"其他",IIf([行業別]=7,"烘焙材料行",IIf([行業別]=8,"百貨量販業",IIf([行業別]=9,"飯店業")))))))))
2011年11月13日 星期日
SA,SD與SE
引用來源
--
做軟體開發專案規劃時, 常會碰到助理問我一個問題, SA,SD和SE的差別在那裡 ?
這個問題我以前也有過, 還頗為困擾, 系統分析和系統設計及系統工程到底有什麼差別 ? SA和SD的工作又有何不同 ? 這兩者的養成教育又有何差異 ?在過去, SA,SD及SE的確很難區分, 甚至這些角色常常會透過軟體工程師來混合發展。
隨著IT領域的發展, SA,SD及SE漸漸的成為了大型專案必需要的專業分工, 這三者間是有相當的差異的, 不管是養成過程, 甚或是未來的發展, 都大相徑庭, 而要成為一名稱職的PM, 是要能區分出這三者的差異, 才能妥善的安排工作的。
[SA,系統分析師]
SA是 System Analysis 的縮寫, 一般稱為系統分析, 主要的工作就是透過一系列的分析工作, 把客戶想要的結果產生方式, 以各種文件表達出來, 讓開發團隊可以根據這些文件實作出這個結果。
這樣的解釋比較文縐縐一點, 用個通俗一點的方式比喻, 就像是要做出一道宮保雞丁時, 就會有食譜一樣, 裡面會介紹需要的材料及做菜的順序, 然後裡面也會強調要以怎樣手法才能產生出某種效果, 以促進色香味。
這樣的過程裡, SA是較為偏重於在工作流程和處理邏輯的, 透過SA, 開發團隊才可以理出整個系統的架構, 一種做事的脈絡, 以及系統和工作間的關連性, 最重要的, 是這些結果都會被SA呈現在文件中, 而非放在少數人的腦袋裡。
SA不僅止是要針對電腦裡的東西去運作及規劃, 還包括了現實世界裡的實體流程及組織。在很多的情況下, 配合新系統的組織及流程, 是要由SA來執行的。總結起來, 在一個開發案裡, SA執行以下的工作:
· 藉由系統需求書, 使用者的現有標準作業流程來建立出符合期望的新作業流程及搭配流程的系統功能及模組規劃
· 依據功能及模組規劃案, 定出初步的資料庫內容及系統與使用者間的權限搭配規範
· 定出各個軟體零件的規範, 如物件, 函數庫, ...等等
· 設計新的標準作業流程, 並把系統功能或模組綁入這些流程中
· S.A依據客戶的環境及需求, 尋找合適的SD來搭配
而SA也有以下的特色:
· 對於系統在怎樣的環境及用什麼開發工具, 並不十分在意, 良好的S.A產生出來的文件, 使用不同的開發工具都應該可以完成, 產生相同的結果, 但那一種最合適, 由SD決定
· SA偏重於流程及執行邏輯的表達
· SA著重於軟體邏輯, 對開發工具的學習並不是十分重要, 所以會一種語言即可, 主要是以該語言工具來實踐邏輯觀。
· SA一定要有全局觀, 也就是不能拘泥於一個角度或是一個局部去思考問題, 這一點是尋找優秀SA時最困難的。因為在規劃模組及功能時, 一定要同時考量到所有直接相關及間接相關的程序及邏輯問題, 因此要有全局觀。
相較於SD, SA更側重在邏輯及工作順序搭配的表達, SA並不需要去關切使用什麼作業系統或是什麼開發工具, 如前特色所述, 好的SA文件, 可以用任何一種開發工具來實現。當然, SA不受限於IT技術, 但卻會有專業領域的限制。
很少有SA同時專精於數個領域的, 熟悉汽車業運作規範的SA, 在金融業的開發案裡, 就很難討好, 反之亦然。但SD沒有這種限制, 基本上SD可以和任何行業的專案開發團隊配合運作。
會如此的原因是SA是偏重於流程及管理分析及重新再造工作的。而作業流程, 除了少數領域裡共通性高, 在核心流程上, 是需要長期鑽研的。前面提及的汽車及金融業就是一例。
所以, 一個SA必需具備以下的能力,資歷及專業訓練:
1. 至少熟悉一種程式開發語言
2. 熟悉軟體工程, 對於開發工具的元素及特色熟悉
3. 對管理制度或作業流程設計熟悉
4. 熟悉UML或類似的系統描述工具
5. 邏輯能力良好
6. 良好的溝通能力, 主要作為瞭解需求之用
7. 相關的業界熟悉度
在三者之中, SA是最接近PM的, 所以SA在做生涯規劃時, 不妨以PM做為下一個發展的專業目標。
[SD, 系統設計師]
一般來說, SD在生涯規劃裡, 並不是SA或是PM。當然, 一定要硬來一次也沒有什麼不可以, 但要走這條路, 就要趁早轉職, 因為SD畢竟是較為幕後的工作, 在與客戶的溝通協調上, 並不會有太高的要求, 也較不需要公司管理層面的全局觀。
表面上看起來, SD沒有SA那麼多的工作要求, 但實際上SD是最需要天賦的工作, 不管是畫面的構成, 操作的手順及調整, 甚至於元件的定義及物件的規範, 全都需要一些天賦。很多軟體, 功能很強, 但怎麼看怎麼不順眼, 或者怎麼用就怎麼憋扭, 功能帶來的效益, 全都被這些毛病給遮蓋掉了, 這就是SD的問題。
另外, SD也扮演了系統最佳化的推手。SA所規劃出來的要求及佈置, 都只是邏輯上的構思, 在不同的工具上, 可能有更好的方法可以表現, 也可能會難以展示, 這都需要藉由SD對使用環境及開發工具的瞭解, 來進行調整和規劃。
舉例來說, 同樣是一套財務軟體, 在WINDOWS XP, MAC, X WINDOWS下, 就會有很不一樣的展現模式和技巧。如果再搭配上不同的開發工具, 如C++, JAVA, .NET, PHP, ...那差異更多。對SA而言, 這些東西他都不用去考慮, 但SD就不同了, 這些不同的地方, 並不僅僅只是如此而已, 有時還會包括了開發成本及時間問題, SD的重要度, 由此可知。
在一個客製化專案裡, SD的工作內容如下:
· 設計畫面元素規範
· 設計頁面結構及規則
· 設計系統操作畫面, 並編定欄位規範及防呆處理
· 設計權限管理與系統操作機制
· 撰寫使用手冊
· 調整DB之各項定義, 使其符合畫面欄位規範及操作搭配
· 配合SA撰寫系統開發文件, 供程式師CODING之用
· 撰寫UI(使用者介面)測試計劃書
而做為一名稱職的SD, 以下的條件, 是必要的:
1. 至少對一個作業系統極為熟悉, 對於這個作業系統的各個元件特性及API, 有充分的瞭解
2. 熟悉2種以上的開發工具, 而專案所需的工具, 必需是其擅長的之一, 其熟悉度包含了標準安裝裡的各個函數庫, 系統常數, 物件定義, 語法, 主要的輔助工具開發廠商, 及重要的工具使用方法
3. 具一定的美學感
4. 至少能使用一種繪圖工具軟體
5. 曾經擔任職業軟體工程師三年以上
可以這樣說, SA給了系統靈魂和神經系統, SD則是給了系統軀體和外觀, 兩者的結合, 才能產生出正確, 美觀又好用的系統。如果你覺得自己是個不太愛和太多人打交道的IT人, 又對使用者介面有那麼點執著及天賦, 那麼, SD絕對是適合你的好選擇。
[SE, 系統工程師]
就某種角度來看, SE對PM而言, 算是萬金油, 只要做IT專案, 那就一定用得上, 差別只是要選那一個專業的SE而已。系統建置安裝要SE, 使用者環境要SE, 甚至到硬體選擇及佈建, 都要用到SE, 有什麼IT專案跟這個沒有關係呢 ?
當然, 雖然SE是到處都吃得開, 但相對的也是專案裡面最沈默及少有聲音的一群。他們的工作基本上就是建構出一個可以執行系統的環境, 系統要如何展現, SE可以給SA和SD一些建議, 但建議時機通常都是在系統運行出了些非系統可以掌握的問題後。
系統工程師基本條件上, 和SD最為接近, 但有一點不同, 就是不需要有很好的軟體開發經驗, 也就是不太需要會寫程式。但要對作業系統, 服務器系統, 網路運用環境有相當程度的瞭解。
SE通常是三者中最為博學一員, 好的SE雖然不一定要程式寫的呱呱叫, 但卻不能對編程一無所知, 對作業系統及開發工具也要有一定的熟悉度, 甚至部份網管有關的工作也要有所涉獵, 所以算得上是專案裡的萬金油。
在專案裡, SE所要執行的工作如下:
· 規劃及建置系統執行環境
· 安裝及設定使用者端環境
· SERVER安裝及設定
· 提供環境設置竟見給SA及PM
· 最佳化系統可靠度及效度
· 撰寫可靠度及效能測試計劃書
· 對電腦及相關週邊設備有一定熟悉度
而一名SE則有下列基本要求:
1. 至少熟悉一種作業系統, 尤其是讓系統的設定及微調等相關技術
2. 至少熟悉一種網路伺服器作業系統, 對如何設定及最佳化熟悉
3. 曾任軟體工程師職務一年以上或熟悉一種開發工具
4. 對網路環境有一定的認識, 尤其是一些通訊設置
5. 熟悉可靠度及效能的評估方法, 並瞭解與系統環境相關之設定
基本上, 如果擁有了像SD一樣的技術背景及個性, 但在美學上實在令人不敢恭維, 那麼SE算是極佳的選擇了。一般而言, SE的下一個生涯規劃, 會比較偏重於技術性兵種, 像是DBA或是網管, 對於IT產品比較有狂熱或愛好的人, SE是極佳的出路。
[在專案中的運用時機]
基本上SE是萬金油, 只要是IT的案子裡就一定要塞一個SE進去, 因為沒有IT專案不需要使用工程技術的, 差別只在使用何種工程技術而已。在套裝軟體的導入專案裡, SE負責處理軟體使用環境, 解決非系統性問題, 安置及調整資料庫和網路環境, 然後安裝啟動。所有系統運行所需要的條件, 都要由SE來解決和處理, 但這些工作全都不會出現在眾人的面前, 但卻又重要無比, 算得上是幕後的英雄。
會同時運用到SA,SD及SE的專案, 還是以客製化開發為主的。
在開發型專案裡, SA團隊要負責初期的需求調查及整體架構的規劃, 將所有的系統開發工作內容轉化成井井有條的文件, 並且適度的分割及派送, 並確保未來這些被分割的開發結果能夠在未來可以正確運作。
SD 則在SA的文件中去尋求系統呈現的一致性, 易用性及保證開發工具可以正確無誤的展現SA的要求結果。所以SD要負責操作界面的外觀設計, 訂定一致的展現規範, 設計系統操作畫面及操作手順, 同時配合SA完成系統開發文件。基本上, 開發文件中, 是包含系統使用手冊初稿的。
SD在設計時, 必需與SA充分配合, 以確保設計的系統符合需求及運作要求。
除了上述的工作內容外, 這三者都要撰寫測試計劃, SA著重在於資料的流動符合原先規劃的順序及結果測試, SD則著重在操作畫面中的防呆測試及操作介面的正確性, 而SE則在系統可靠度上進行規劃。
[軟體工程師何時轉職 ?]
每一個寫程式的人心裡都明白, 這工作不可能做一輩子。不單單是體力及腦力問題, 最重要的是寫程式, 經濟價值實在有限。
我不會否認有很多的程式高手, 但重點不在於你有多優秀, 而是有多少老闆願意付出和你努力成正比的薪資來顧用你。不是沒有這種工作, 而是如同鳳毛麟角, 而且, 這種工作通常你也做不久, 因為壓力太大, 消耗青春太劇烈了。
退一步來說, 你也不值得付出這麼多, 在良好的SA及SD的規劃下, 工程師只要達成一般標準, 就可以解決掉九成以上的軟體開發需求, 除非是機緣巧合, 或是你很有興趣, 否則另外那一成的工作, 你是很難有機會碰上, 或者, 就算碰上, 也沒法子養活你一輩子。
軟體工程師總有一天要轉職的, 這是他們的宿命。
當要轉職時, 他們有幾個選擇, SA, SD, SE, 出去當老闆及換一行等諸多選擇。看起來雖多, 但其實晚景淒涼, 因為寫程式都是關起來寫, 長期自閉的結果, 當他們想轉職時, 很難擁有足夠的人脈來支撐他們換個前途光明的事業。一般人羨慕IT人的高薪, 卻不曉得只是寅支卯糧, 沒有妥善的規劃, 後勢看跌的。
前面的五個選項, 基本上最後兩項只是充場面, 只有少數人才能選那兩個, 大多數軟體工程師還是要在前三者中選一個來發展的。
SA看起來最風光, 未來也是潛力最好的, 但很遺憾的, 軟體工程師裡, 只有少數人適合這個職務。因為這個工作是很需要和別人打交道的, 而好的軟體工程師通常這一點非常不擅長。
因此, 如果你自認為擅於溝通, 三姑六婆都是你的紅顏知己, 邏輯能力不錯, 又對管理有興趣, 那麼SA是你很好的選擇, 程式功力並不是你要考慮的重點。
相對的, 你對使用者介面很有心得, 而且在美感上也獲得了同事的一致讚賞, 程式功力也有那麼一點自信, 討厭和不是搞IT的人打屁聊天, 那不要懷疑, SD是你最佳的歸宿。
最後, 你覺得IT的世界對你充滿了吸引力, 無論是作業系統, 開發工具或是軟體及IT設備都是如此的吸引你, 人與人的接觸對你來說並不是人生的首要需求, 層出不窮的IT科技讓你陶醉其中, 那麼, SE絕對是你的首選。
要如何轉職, 每一個軟體工程師是要誠實面對自己的, 而不是依前途來決定自己要選什麼職務, 如果你依這種方式選, 以我個人在職場生涯的經驗, 這樣的人很難散發出光芒, 也難以有他期望的成就。所以, 現在在寫程式, 正在想要轉職的工程師, 請謹慎而且誠實的面對自己, 做出恰當的選擇。
[結語]
以上是個人提供給對於SA, SD及SE或到困惑的朋友, 做為參考及工作分配的依據。這三者的產生, 其實也是源於目前IT技術的成長過於快速, 所以必需針對軟體工程進行適切的分工, 才能應付好日益複雜的IT環境。
--
做軟體開發專案規劃時, 常會碰到助理問我一個問題, SA,SD和SE的差別在那裡 ?
這個問題我以前也有過, 還頗為困擾, 系統分析和系統設計及系統工程到底有什麼差別 ? SA和SD的工作又有何不同 ? 這兩者的養成教育又有何差異 ?在過去, SA,SD及SE的確很難區分, 甚至這些角色常常會透過軟體工程師來混合發展。
隨著IT領域的發展, SA,SD及SE漸漸的成為了大型專案必需要的專業分工, 這三者間是有相當的差異的, 不管是養成過程, 甚或是未來的發展, 都大相徑庭, 而要成為一名稱職的PM, 是要能區分出這三者的差異, 才能妥善的安排工作的。
[SA,系統分析師]
SA是 System Analysis 的縮寫, 一般稱為系統分析, 主要的工作就是透過一系列的分析工作, 把客戶想要的結果產生方式, 以各種文件表達出來, 讓開發團隊可以根據這些文件實作出這個結果。
這樣的解釋比較文縐縐一點, 用個通俗一點的方式比喻, 就像是要做出一道宮保雞丁時, 就會有食譜一樣, 裡面會介紹需要的材料及做菜的順序, 然後裡面也會強調要以怎樣手法才能產生出某種效果, 以促進色香味。
這樣的過程裡, SA是較為偏重於在工作流程和處理邏輯的, 透過SA, 開發團隊才可以理出整個系統的架構, 一種做事的脈絡, 以及系統和工作間的關連性, 最重要的, 是這些結果都會被SA呈現在文件中, 而非放在少數人的腦袋裡。
SA不僅止是要針對電腦裡的東西去運作及規劃, 還包括了現實世界裡的實體流程及組織。在很多的情況下, 配合新系統的組織及流程, 是要由SA來執行的。總結起來, 在一個開發案裡, SA執行以下的工作:
· 藉由系統需求書, 使用者的現有標準作業流程來建立出符合期望的新作業流程及搭配流程的系統功能及模組規劃
· 依據功能及模組規劃案, 定出初步的資料庫內容及系統與使用者間的權限搭配規範
· 定出各個軟體零件的規範, 如物件, 函數庫, ...等等
· 設計新的標準作業流程, 並把系統功能或模組綁入這些流程中
· S.A依據客戶的環境及需求, 尋找合適的SD來搭配
而SA也有以下的特色:
· 對於系統在怎樣的環境及用什麼開發工具, 並不十分在意, 良好的S.A產生出來的文件, 使用不同的開發工具都應該可以完成, 產生相同的結果, 但那一種最合適, 由SD決定
· SA偏重於流程及執行邏輯的表達
· SA著重於軟體邏輯, 對開發工具的學習並不是十分重要, 所以會一種語言即可, 主要是以該語言工具來實踐邏輯觀。
· SA一定要有全局觀, 也就是不能拘泥於一個角度或是一個局部去思考問題, 這一點是尋找優秀SA時最困難的。因為在規劃模組及功能時, 一定要同時考量到所有直接相關及間接相關的程序及邏輯問題, 因此要有全局觀。
相較於SD, SA更側重在邏輯及工作順序搭配的表達, SA並不需要去關切使用什麼作業系統或是什麼開發工具, 如前特色所述, 好的SA文件, 可以用任何一種開發工具來實現。當然, SA不受限於IT技術, 但卻會有專業領域的限制。
很少有SA同時專精於數個領域的, 熟悉汽車業運作規範的SA, 在金融業的開發案裡, 就很難討好, 反之亦然。但SD沒有這種限制, 基本上SD可以和任何行業的專案開發團隊配合運作。
會如此的原因是SA是偏重於流程及管理分析及重新再造工作的。而作業流程, 除了少數領域裡共通性高, 在核心流程上, 是需要長期鑽研的。前面提及的汽車及金融業就是一例。
所以, 一個SA必需具備以下的能力,資歷及專業訓練:
1. 至少熟悉一種程式開發語言
2. 熟悉軟體工程, 對於開發工具的元素及特色熟悉
3. 對管理制度或作業流程設計熟悉
4. 熟悉UML或類似的系統描述工具
5. 邏輯能力良好
6. 良好的溝通能力, 主要作為瞭解需求之用
7. 相關的業界熟悉度
在三者之中, SA是最接近PM的, 所以SA在做生涯規劃時, 不妨以PM做為下一個發展的專業目標。
[SD, 系統設計師]
一般來說, SD在生涯規劃裡, 並不是SA或是PM。當然, 一定要硬來一次也沒有什麼不可以, 但要走這條路, 就要趁早轉職, 因為SD畢竟是較為幕後的工作, 在與客戶的溝通協調上, 並不會有太高的要求, 也較不需要公司管理層面的全局觀。
表面上看起來, SD沒有SA那麼多的工作要求, 但實際上SD是最需要天賦的工作, 不管是畫面的構成, 操作的手順及調整, 甚至於元件的定義及物件的規範, 全都需要一些天賦。很多軟體, 功能很強, 但怎麼看怎麼不順眼, 或者怎麼用就怎麼憋扭, 功能帶來的效益, 全都被這些毛病給遮蓋掉了, 這就是SD的問題。
另外, SD也扮演了系統最佳化的推手。SA所規劃出來的要求及佈置, 都只是邏輯上的構思, 在不同的工具上, 可能有更好的方法可以表現, 也可能會難以展示, 這都需要藉由SD對使用環境及開發工具的瞭解, 來進行調整和規劃。
舉例來說, 同樣是一套財務軟體, 在WINDOWS XP, MAC, X WINDOWS下, 就會有很不一樣的展現模式和技巧。如果再搭配上不同的開發工具, 如C++, JAVA, .NET, PHP, ...那差異更多。對SA而言, 這些東西他都不用去考慮, 但SD就不同了, 這些不同的地方, 並不僅僅只是如此而已, 有時還會包括了開發成本及時間問題, SD的重要度, 由此可知。
在一個客製化專案裡, SD的工作內容如下:
· 設計畫面元素規範
· 設計頁面結構及規則
· 設計系統操作畫面, 並編定欄位規範及防呆處理
· 設計權限管理與系統操作機制
· 撰寫使用手冊
· 調整DB之各項定義, 使其符合畫面欄位規範及操作搭配
· 配合SA撰寫系統開發文件, 供程式師CODING之用
· 撰寫UI(使用者介面)測試計劃書
而做為一名稱職的SD, 以下的條件, 是必要的:
1. 至少對一個作業系統極為熟悉, 對於這個作業系統的各個元件特性及API, 有充分的瞭解
2. 熟悉2種以上的開發工具, 而專案所需的工具, 必需是其擅長的之一, 其熟悉度包含了標準安裝裡的各個函數庫, 系統常數, 物件定義, 語法, 主要的輔助工具開發廠商, 及重要的工具使用方法
3. 具一定的美學感
4. 至少能使用一種繪圖工具軟體
5. 曾經擔任職業軟體工程師三年以上
可以這樣說, SA給了系統靈魂和神經系統, SD則是給了系統軀體和外觀, 兩者的結合, 才能產生出正確, 美觀又好用的系統。如果你覺得自己是個不太愛和太多人打交道的IT人, 又對使用者介面有那麼點執著及天賦, 那麼, SD絕對是適合你的好選擇。
[SE, 系統工程師]
就某種角度來看, SE對PM而言, 算是萬金油, 只要做IT專案, 那就一定用得上, 差別只是要選那一個專業的SE而已。系統建置安裝要SE, 使用者環境要SE, 甚至到硬體選擇及佈建, 都要用到SE, 有什麼IT專案跟這個沒有關係呢 ?
當然, 雖然SE是到處都吃得開, 但相對的也是專案裡面最沈默及少有聲音的一群。他們的工作基本上就是建構出一個可以執行系統的環境, 系統要如何展現, SE可以給SA和SD一些建議, 但建議時機通常都是在系統運行出了些非系統可以掌握的問題後。
系統工程師基本條件上, 和SD最為接近, 但有一點不同, 就是不需要有很好的軟體開發經驗, 也就是不太需要會寫程式。但要對作業系統, 服務器系統, 網路運用環境有相當程度的瞭解。
SE通常是三者中最為博學一員, 好的SE雖然不一定要程式寫的呱呱叫, 但卻不能對編程一無所知, 對作業系統及開發工具也要有一定的熟悉度, 甚至部份網管有關的工作也要有所涉獵, 所以算得上是專案裡的萬金油。
在專案裡, SE所要執行的工作如下:
· 規劃及建置系統執行環境
· 安裝及設定使用者端環境
· SERVER安裝及設定
· 提供環境設置竟見給SA及PM
· 最佳化系統可靠度及效度
· 撰寫可靠度及效能測試計劃書
· 對電腦及相關週邊設備有一定熟悉度
而一名SE則有下列基本要求:
1. 至少熟悉一種作業系統, 尤其是讓系統的設定及微調等相關技術
2. 至少熟悉一種網路伺服器作業系統, 對如何設定及最佳化熟悉
3. 曾任軟體工程師職務一年以上或熟悉一種開發工具
4. 對網路環境有一定的認識, 尤其是一些通訊設置
5. 熟悉可靠度及效能的評估方法, 並瞭解與系統環境相關之設定
基本上, 如果擁有了像SD一樣的技術背景及個性, 但在美學上實在令人不敢恭維, 那麼SE算是極佳的選擇了。一般而言, SE的下一個生涯規劃, 會比較偏重於技術性兵種, 像是DBA或是網管, 對於IT產品比較有狂熱或愛好的人, SE是極佳的出路。
[在專案中的運用時機]
基本上SE是萬金油, 只要是IT的案子裡就一定要塞一個SE進去, 因為沒有IT專案不需要使用工程技術的, 差別只在使用何種工程技術而已。在套裝軟體的導入專案裡, SE負責處理軟體使用環境, 解決非系統性問題, 安置及調整資料庫和網路環境, 然後安裝啟動。所有系統運行所需要的條件, 都要由SE來解決和處理, 但這些工作全都不會出現在眾人的面前, 但卻又重要無比, 算得上是幕後的英雄。
會同時運用到SA,SD及SE的專案, 還是以客製化開發為主的。
在開發型專案裡, SA團隊要負責初期的需求調查及整體架構的規劃, 將所有的系統開發工作內容轉化成井井有條的文件, 並且適度的分割及派送, 並確保未來這些被分割的開發結果能夠在未來可以正確運作。
SD 則在SA的文件中去尋求系統呈現的一致性, 易用性及保證開發工具可以正確無誤的展現SA的要求結果。所以SD要負責操作界面的外觀設計, 訂定一致的展現規範, 設計系統操作畫面及操作手順, 同時配合SA完成系統開發文件。基本上, 開發文件中, 是包含系統使用手冊初稿的。
SD在設計時, 必需與SA充分配合, 以確保設計的系統符合需求及運作要求。
除了上述的工作內容外, 這三者都要撰寫測試計劃, SA著重在於資料的流動符合原先規劃的順序及結果測試, SD則著重在操作畫面中的防呆測試及操作介面的正確性, 而SE則在系統可靠度上進行規劃。
[軟體工程師何時轉職 ?]
每一個寫程式的人心裡都明白, 這工作不可能做一輩子。不單單是體力及腦力問題, 最重要的是寫程式, 經濟價值實在有限。
我不會否認有很多的程式高手, 但重點不在於你有多優秀, 而是有多少老闆願意付出和你努力成正比的薪資來顧用你。不是沒有這種工作, 而是如同鳳毛麟角, 而且, 這種工作通常你也做不久, 因為壓力太大, 消耗青春太劇烈了。
退一步來說, 你也不值得付出這麼多, 在良好的SA及SD的規劃下, 工程師只要達成一般標準, 就可以解決掉九成以上的軟體開發需求, 除非是機緣巧合, 或是你很有興趣, 否則另外那一成的工作, 你是很難有機會碰上, 或者, 就算碰上, 也沒法子養活你一輩子。
軟體工程師總有一天要轉職的, 這是他們的宿命。
當要轉職時, 他們有幾個選擇, SA, SD, SE, 出去當老闆及換一行等諸多選擇。看起來雖多, 但其實晚景淒涼, 因為寫程式都是關起來寫, 長期自閉的結果, 當他們想轉職時, 很難擁有足夠的人脈來支撐他們換個前途光明的事業。一般人羨慕IT人的高薪, 卻不曉得只是寅支卯糧, 沒有妥善的規劃, 後勢看跌的。
前面的五個選項, 基本上最後兩項只是充場面, 只有少數人才能選那兩個, 大多數軟體工程師還是要在前三者中選一個來發展的。
SA看起來最風光, 未來也是潛力最好的, 但很遺憾的, 軟體工程師裡, 只有少數人適合這個職務。因為這個工作是很需要和別人打交道的, 而好的軟體工程師通常這一點非常不擅長。
因此, 如果你自認為擅於溝通, 三姑六婆都是你的紅顏知己, 邏輯能力不錯, 又對管理有興趣, 那麼SA是你很好的選擇, 程式功力並不是你要考慮的重點。
相對的, 你對使用者介面很有心得, 而且在美感上也獲得了同事的一致讚賞, 程式功力也有那麼一點自信, 討厭和不是搞IT的人打屁聊天, 那不要懷疑, SD是你最佳的歸宿。
最後, 你覺得IT的世界對你充滿了吸引力, 無論是作業系統, 開發工具或是軟體及IT設備都是如此的吸引你, 人與人的接觸對你來說並不是人生的首要需求, 層出不窮的IT科技讓你陶醉其中, 那麼, SE絕對是你的首選。
要如何轉職, 每一個軟體工程師是要誠實面對自己的, 而不是依前途來決定自己要選什麼職務, 如果你依這種方式選, 以我個人在職場生涯的經驗, 這樣的人很難散發出光芒, 也難以有他期望的成就。所以, 現在在寫程式, 正在想要轉職的工程師, 請謹慎而且誠實的面對自己, 做出恰當的選擇。
[結語]
以上是個人提供給對於SA, SD及SE或到困惑的朋友, 做為參考及工作分配的依據。這三者的產生, 其實也是源於目前IT技術的成長過於快速, 所以必需針對軟體工程進行適切的分工, 才能應付好日益複雜的IT環境。
2011年11月11日 星期五
access dateadd
參考來源
---
真是,以為和 vb6 一樣勒! 結果是要用 西元格式來作:加或減年度
如下,亦可用在TSQL
Update TABLE Set [date due] = DateAdd("yyyy", 2, [date due]) Where (test=x);
---
真是,以為和 vb6 一樣勒! 結果是要用 西元格式來作:加或減年度
如下,亦可用在TSQL
Update TABLE Set [date due] = DateAdd("yyyy", 2, [date due]) Where (test=x);
2011年11月10日 星期四
2011年11月9日 星期三
vbnet 定義字串長度
引用參考
---------
Structure Person
Public ID As Integer
Public MonthlySalary As Decimal
Public LastReviewDate As Long
End Structure
注意
VBFixedStringAttribute 是信息性的属性,不能用于将可变长度字符串转换为固定长度字符串。此属性的作用是修改那些识别 VBFixedStringAttribute 的方法或 API 调用(如 Len 和 FilePut 函数)使用结构中的字符串以及非局部变量的方式。请记住,此属性不会更改字符串本身的实际长度。
备注
默认情况下,Visual Basic 字符串为可变长度的字符串。在使用 Visual Basic 文件输入和输出函数(如需要固定长度字符串的 FileGet 和 FilePut)时,该属性非常有用。
注意
VBFixedStringAttribute 属性以字节而不是字符为单位指定字符串长度。
----
我的解讀與用法:
Public Class Form1
Structure GetTransData
End Structure
Dim GTdata As GetTransData
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
GTdata.trans_type = "12111"
MessageBox.Show(Len(GTdata) & " " & GTdata.trans_type.Length & " " & GTdata.trans_type)
End Sub
End Class
這答案會是: 2, 5, 12111
只是騙系統總長度是2,實際還是依儲存的為主;所以定義長度沒什麼
信用卡機
引用:
--
1.LRC是checksum用.應是針對(Data[]+ETX)作XOR的結果.
Data=Data[0];
for ( i=1; i < length; i++ ) Data = Data xor Data[i];
LRC=Data xor ETX;
2.在將 (header data if need)+ Data[]+ETX+LRC +(tail data if need) 送到前端設備.
CRC、Checksum、VRC、LRC之比較(1.使用bit數的多寡 2.作法上的使用 3.佔記憶空間 4.是否會誤判之排行榜)
CRC(循環冗餘檢查碼,Cyclic Redundancy Check),目前較常使用的位元數目有8、16或32,一般縮寫為CRC-8、CRC-16、CRC-32。根據理論統計,CRC-16可完全偵測資料區塊內單一或兩個位元的錯誤、奇數個位元的錯誤、連續16個位元或少於此數的錯誤,超過17個連續位元的錯誤偵測率則有99.9969%,其它位元長度的錯誤偵測率則可達99.9984%。XMODEM、Kermit等通訊協定,PC 的磁碟機、FDDI、乙太網路和「光纖通道」使用CRC驗證。
Checksum(總和檢查)使用的位元數沒有特別提到。Apple個人電腦的磁碟機是利用checksum驗證資料的正確性。
VRC(垂直冗餘檢查,Vertical Redundancy Check)是對每一個傳送字元(一般是8位元)都增加一個額外位元。
LRC(縱向冗餘檢查,Longitudinal Redundancy Check)也是對每一個傳送字元(一般是8位元)都增加一個額外位元。磁帶資料及透過通訊線路傳送的資料可用LRC驗證。
錯誤檢查所佔用的記憶體空間應與使用的位元數有正相關,誤判的機率應與使用的位元數有負相關,但是詳細的數字還是請您查看書籍與相關研究報告(不過對於VRC和LRC的討論及比較相當少)。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
private
Procedure ConnectPrint(var aHandle : THandle);//開始連結COM1
function GetTransData : String;
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
aHandle : THandle;
lrc : Longword;
s, s1 : string;
i : Integer;
bb : byte;
begin
//開啟COM1
ConnectPrint(aHandle);
//送出要求(144BYTE)
s := GetTransData;
s1 := s;
//取得lrc的值
for i := 0 to length(s) - 1 do
begin
bb := byte(s[i]);
s1[i] := chr(bb xor 3);
end;
S := PCHAR(CHR($02) + S + CHR($03) + S1);
WriteFile(aHandle, S , 290, lrc, nil);
//關閉COM1
CloseHandle(aHandle);
end;
procedure TForm1.ConnectPrint(var aHandle : THandle);
var
Temp : String;
dcb : _DCB;
lrc : Longword;
begin
temp := 'COM1';
aHandle := CreateFile(PChar(temp),
GENERIC_READ OR GENERIC_WRITE,
0,
nil,
OPEN_EXISTING,
0,
0 );
end;
function TForm1.GetTransData: String;
var
aString : String;
begin
{Trans Type ( 2)
Host ID ( 2)
Invoice No ( 6)
Card No (19)
Card Exp Date ( 4)
Trans Amt (12)
Trans Date ( 6)
Trans Time ( 6)
Approval Code ( 9)
Amount 1 (12)
Resp Code ( 4)
Terminal Id ( 8)
Ref No (12)
Amount2 (12)
StoreID (16)
Reserved (13)
}
aString := '01'
+ '02'
+ '000000'
+ '0000000000000000000'
+ '0000'
+ '000000128000'
+ '000000' //6
+ '000000' //6
+ '000000000'//9
+ '000000000000'
+ '0000'
+ '00000000'
+ '00000000'
+ '000000000000'//12
+ '000000000000'//12
+ '00000000000000000'//17
+ '0000000000000';//13
Result := aString;
end;
end.
CRC、Checksum、VRC、LRC之比較
引用參考1
引用參考2
---
1.LRC是checksum用.應是針對(Data[]+ETX)作XOR的結果.
Data=Data[0];
for ( i=1; i < length; i++ ) Data = Data xor Data[i];
LRC=Data xor ETX;
2.在將 (header data if need)+ Data[]+ETX+LRC +(tail data if need) 送到前端設備.
CRC、Checksum、VRC、LRC之比較(1.使用bit數的多寡 2.作法上的使用 3.佔記憶空間 4.是否會誤判之排行榜)
CRC(循環冗餘檢查碼,Cyclic Redundancy Check),目前較常使用的位元數目有8、16或32,一般縮寫為CRC-8、CRC-16、CRC-32。根據理論統計,CRC-16可完全偵測資料區塊內單一或兩個位元的錯誤、奇數個位元的錯誤、連續16個位元或少於此數的錯誤,超過17個連續位元的錯誤偵測率則有99.9969%,其它位元長度的錯誤偵測率則可達99.9984%。XMODEM、Kermit等通訊協定,PC 的磁碟機、FDDI、乙太網路和「光纖通道」使用CRC驗證。
Checksum(總和檢查)使用的位元數沒有特別提到。Apple個人電腦的磁碟機是利用checksum驗證資料的正確性。
VRC(垂直冗餘檢查,Vertical Redundancy Check)是對每一個傳送字元(一般是8位元)都增加一個額外位元。
LRC(縱向冗餘檢查,Longitudinal Redundancy Check)也是對每一個傳送字元(一般是8位元)都增加一個額外位元。磁帶資料及透過通訊線路傳送的資料可用LRC驗證。
錯誤檢查所佔用的記憶體空間應與使用的位元數有正相關,誤判的機率應與使用的位元數有負相關,但是詳細的數字還是請您查看書籍與相關研究報告(不過對於VRC和LRC的討論及比較相當少)。
引用參考2
---
1.LRC是checksum用.應是針對(Data[]+ETX)作XOR的結果.
Data=Data[0];
for ( i=1; i < length; i++ ) Data = Data xor Data[i];
LRC=Data xor ETX;
2.在將 (header data if need)+ Data[]+ETX+LRC +(tail data if need) 送到前端設備.
CRC、Checksum、VRC、LRC之比較(1.使用bit數的多寡 2.作法上的使用 3.佔記憶空間 4.是否會誤判之排行榜)
CRC(循環冗餘檢查碼,Cyclic Redundancy Check),目前較常使用的位元數目有8、16或32,一般縮寫為CRC-8、CRC-16、CRC-32。根據理論統計,CRC-16可完全偵測資料區塊內單一或兩個位元的錯誤、奇數個位元的錯誤、連續16個位元或少於此數的錯誤,超過17個連續位元的錯誤偵測率則有99.9969%,其它位元長度的錯誤偵測率則可達99.9984%。XMODEM、Kermit等通訊協定,PC 的磁碟機、FDDI、乙太網路和「光纖通道」使用CRC驗證。
Checksum(總和檢查)使用的位元數沒有特別提到。Apple個人電腦的磁碟機是利用checksum驗證資料的正確性。
VRC(垂直冗餘檢查,Vertical Redundancy Check)是對每一個傳送字元(一般是8位元)都增加一個額外位元。
LRC(縱向冗餘檢查,Longitudinal Redundancy Check)也是對每一個傳送字元(一般是8位元)都增加一個額外位元。磁帶資料及透過通訊線路傳送的資料可用LRC驗證。
錯誤檢查所佔用的記憶體空間應與使用的位元數有正相關,誤判的機率應與使用的位元數有負相關,但是詳細的數字還是請您查看書籍與相關研究報告(不過對於VRC和LRC的討論及比較相當少)。
取得ACCESS資料庫內所有資料表相關資訊
'須引用Microsoft ActiveX Data Objects 2.5 Library
Private Sub Command1_Click()
Dim conConnection As New ADODB.Connection
Dim cmdCommand As New ADODB.Command
Dim rstRecordSet As New ADODB.Recordset
conConnection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & _
App.Path & "\" & "database.mdb;Mode=Read|Write"
conConnection.CursorLocation = adUseClient
conConnection.Open
'Get all database tables.
Set TablesSchema = conConnection.OpenSchema(adSchemaTables)
Do While Not TablesSchema.EOF
If TablesSchema("TABLE_TYPE") = "TABLE" Then
'Get all table columns.
Set ColumnsSchema = conConnection.OpenSchema(adSchemaColumns, Array(Empty, Empty, "" & TablesSchema("TABLE_NAME")))
Do While Not ColumnsSchema.EOF
Debug.Print TablesSchema("TABLE_NAME") & ", " & _
ColumnsSchema("COLUMN_NAME")
ColumnsSchema.MoveNext
Loop
End If
TablesSchema.MoveNext
Loop
conConnection.Close
Set conConnection = Nothing
Set cmdCommand = Nothing
Set rstRecordSet = Nothing
End Sub
VB RS232接收資料實作
引用:
--
1.表單中加入 MSComm
2.Form_Load中加入下列程式碼
Private Sub Form_Load()
'設定comport的位置
MSComm1.CommPort = 1
'檢查一下Com1是否被使用了,若被使用了,把Com1關閉並重設.
If (MSComm1.PortOpen) Then MSComm1.PortOpen = False
'設定comport的讀取速率,注意RS232傳送速率,有的是9600,有的是1200,看你的Device而定
MSComm1.Settings = "9600,N,8,1"
'設定DTR線路為高電位
MSComm1.DTREnable = True
'設定讀取的長度
MSComm1.InputLen = 33
'當緩衝區有33bytes則觸發事件
MSComm1.RThreshold = 33
'交握模式設定
MSComm1.Handshaking = MSCOMMLIB.HandshakeConstants.comXOnXoff
'資料格式,走33byte,text模式
MSComm1.InputMode = MSCOMMLIB.InputModeConstants.comInputModeText
'null一樣照收
MSComm1.NullDiscard = False
'打開comport 1
MSComm1.PortOpen = True
Timer1.Enabled = True
MSComm1.RTSEnable = True
End Sub
3.加入MSComm1_OnComm 接收事件
Private Sub MSComm1_OnComm()
Dim TempStr as String
If MSComm1.InBufferCount = 33 Then
TempStr = MSComm1.Input
debug.print "接收資料為:" & TempStr
'這裡就寫你要的邏輯,看怎麼處理資料嚕
end if
End Sub
2011年11月8日 星期二
vbnet SQLite
vbnet 要使用 SQLite 資料庫 (ADO.NET) System.Data.SQLite
一定要採用:SQLite shell 建資料庫 , 用VS 來建資料表,欄位等(亦可有指令來新建)
在使用過程:試了 SQLite Administrator , SQLite Spy 等2個工具去建資料表後
使用 vbnet 要去開資料庫均造成無法開啟的訊息!!
----
底下參考SQLite in VB.net - Page 2 的範例寫的! (至於 VB6 有空再來測)
--
Imports System.Data
Imports System.Data.SQLite
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim SQLconnect As New SQLite.SQLiteConnection()
Dim SQLcommand As SQLiteCommand
SQLconnect.ConnectionString = "Data Source=" & Application.StartupPath & "\test.db3" & ";"
SQLconnect.Open()
SQLcommand = SQLconnect.CreateCommand
SQLcommand.CommandText = "SELECT * FROM test"
Dim SQLreader As SQLiteDataReader = SQLcommand.ExecuteReader()
lst_records.Items.Clear()
While SQLreader.Read()
lst_records.Items.Add(String.Format("ID = {0}, name = {1}", SQLreader(0), SQLreader(1)))
'Optionally use the variable names to identify columns
'De lst_records.Items.Add(String.Format("ID = {0}, Title = {1}, Description = {1}", SQLreader("id"), SQLreader("title"), SQLreader("description")))
End While
SQLcommand.Dispose()
SQLconnect.Close()
End Sub
End Class
一定要採用:SQLite shell 建資料庫 , 用VS 來建資料表,欄位等(亦可有指令來新建)
在使用過程:試了 SQLite Administrator , SQLite Spy 等2個工具去建資料表後
使用 vbnet 要去開資料庫均造成無法開啟的訊息!!
----
底下參考SQLite in VB.net - Page 2 的範例寫的! (至於 VB6 有空再來測)
--
Imports System.Data
Imports System.Data.SQLite
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim SQLconnect As New SQLite.SQLiteConnection()
Dim SQLcommand As SQLiteCommand
SQLconnect.ConnectionString = "Data Source=" & Application.StartupPath & "\test.db3" & ";"
SQLconnect.Open()
SQLcommand = SQLconnect.CreateCommand
SQLcommand.CommandText = "SELECT * FROM test"
Dim SQLreader As SQLiteDataReader = SQLcommand.ExecuteReader()
lst_records.Items.Clear()
While SQLreader.Read()
lst_records.Items.Add(String.Format("ID = {0}, name = {1}", SQLreader(0), SQLreader(1)))
'Optionally use the variable names to identify columns
'De lst_records.Items.Add(String.Format("ID = {0}, Title = {1}, Description = {1}", SQLreader("id"), SQLreader("title"), SQLreader("description")))
End While
SQLcommand.Dispose()
SQLconnect.Close()
End Sub
End Class
vb6中取sqlite最后一行数据
为了查如何取最后一行数据,在网上查了很多,sqlite也不支持top语句,终于让我找到一个利用limit来查询最后一行的办法,如果各位有更简便的方法请不吝赐教。
Dim odb As Object
Dim odb1 As Object
Set odb = CreateObject("LiteX.LiteConnection")
Set odb1 = CreateObject("LiteX.LiteStatement")
odb.open (App.Path & "\test.db")
odb1.ActiveConnection = odb
sql = "select * from tab01"
odb1.prepare (sql)
n = odb1.rowcount '取一共有多少行数据
odb1.Close
sql = "select * from tab01 limit " & n - 1 & ",1" '利用limit语句用法取最后一行的数据
odb1.prepare (sql)
For Each rows In odb1.rows
Label1 = Label1 & rows(0) & " " & rows(1) & vbCrLf
Next
odb1.Close
odb.Close
在vb6中使用sqlite
引用
--
egsvr32 sqlite3.dll
随便是建一个bat文件运行,还是直接在开始菜单运行都可以
压缩文件包中有自动注册bat文件,sqlite3.dll,测试数据库,litex开发文档(英文)
新建表
Dim odb As Object
Set odb = CreateObject("LiteX.LiteConnection")
odb.open (App.Path & "\test.db") '一开始直接建一个空白文件就可以用了
sql = "create table tab01(name text,nl integar)" 'sqlite数据库其实可以不用定义,但是为了以后的转移或者说明,定义下比较方便
odb.execute(sql)
odb.close
插入数据
Dim odb As Object
Set odb = CreateObject("LiteX.LiteConnection")
odb.open (App.Path & "\test.db")
sql = "insert into tab01 values('chen',5)"
odb.execute(sql)
odb.close
查询
Dim odb As Object
Set odb = CreateObject("LiteX.LiteConnection")
odb.open (App.Path & "\test.db")
Dim odb1 As Object
Set odb1 = CreateObject("LiteX.LiteStatement")
odb1.ActiveConnection = odb
label1=""
sql = "select * from tab01"
odb1.prepare (sql)
For Each row In odb1.rows '用.rows属性取出预查询的数据,插入到label1里面
Label1 = Label1 & row(0) & " " & row(1) & vbCrLf '在这个其中row实际上为一个数组,下标从0开始
Next
odb1.close 'prepare方法只能用一次,第二次用之前要关闭一下odb1,或者每用完一次就养成顺手关的好习惯
odb.close
'文档上说odb1这个状态变量可以直接用odb的prepare方法直接创建,但是我试了下,不知道为什么报错,所以改成手工定义,都一样,就是麻烦点
'本来不知道应该怎么定义row这个变量,在说明文档上被称为LiteX.LiteRow。后来试了下,可以定义为Variant,使用过程中没问题。
'本来想在程序中动态加载dll文件,也在网上找到动态加载的代码,但是不知道为什么报错,所以直接改成提前注册了
--
egsvr32 sqlite3.dll
随便是建一个bat文件运行,还是直接在开始菜单运行都可以
压缩文件包中有自动注册bat文件,sqlite3.dll,测试数据库,litex开发文档(英文)
新建表
Dim odb As Object
Set odb = CreateObject("LiteX.LiteConnection")
odb.open (App.Path & "\test.db") '一开始直接建一个空白文件就可以用了
sql = "create table tab01(name text,nl integar)" 'sqlite数据库其实可以不用定义,但是为了以后的转移或者说明,定义下比较方便
odb.execute(sql)
odb.close
插入数据
Dim odb As Object
Set odb = CreateObject("LiteX.LiteConnection")
odb.open (App.Path & "\test.db")
sql = "insert into tab01 values('chen',5)"
odb.execute(sql)
odb.close
查询
Dim odb As Object
Set odb = CreateObject("LiteX.LiteConnection")
odb.open (App.Path & "\test.db")
Dim odb1 As Object
Set odb1 = CreateObject("LiteX.LiteStatement")
odb1.ActiveConnection = odb
label1=""
sql = "select * from tab01"
odb1.prepare (sql)
For Each row In odb1.rows '用.rows属性取出预查询的数据,插入到label1里面
Label1 = Label1 & row(0) & " " & row(1) & vbCrLf '在这个其中row实际上为一个数组,下标从0开始
Next
odb1.close 'prepare方法只能用一次,第二次用之前要关闭一下odb1,或者每用完一次就养成顺手关的好习惯
odb.close
'文档上说odb1这个状态变量可以直接用odb的prepare方法直接创建,但是我试了下,不知道为什么报错,所以改成手工定义,都一样,就是麻烦点
'本来不知道应该怎么定义row这个变量,在说明文档上被称为LiteX.LiteRow。后来试了下,可以定义为Variant,使用过程中没问题。
'本来想在程序中动态加载dll文件,也在网上找到动态加载的代码,但是不知道为什么报错,所以直接改成提前注册了
SQLite使用教學
引用:SQLite使用教學
--
OS X自從10.4後把SQLite這套相當出名的資料庫軟體,放進了作業系統工具集裡。OS X包裝的是第三版的SQLite,又稱SQLite3。這套軟體有幾個特色:
* 軟體屬於公共財(public domain),SQLite可說是某種「美德軟體」(virtueware),作者本人放棄著作權,而給使用SQLite的人以下的「祝福」(blessing):
o May you do good and not evil. 願你行善莫行惡
o May you find forgiveness for yourself and forgive others. 願你原諒自己寬恕他人
o May you share freely, never taking more than you give. 願你寬心與人分享,所取不多於你所施予
* 支援大多數的SQL指令(下面會簡單介紹)。
* 一個檔案就是一個資料庫。不需要安裝資料庫伺服器軟體。
* 完整的Unicode支援(因此沒有跨語系的問題)。
* 速度很快。
目前在OS X 10.4裡,SQLite是以/usr/bin/sqlite3的形式包裝,也就說這是一個命令列工具,必須先從終端機(Terminal.app或其他程式)進入shell之後才能使用。網路上有一些協助使用SQLite的視覺化工具,但似乎都沒有像CocoaMySQL(配合MySQL資料庫使用)那般好用。或許隨時有驚喜也未可知,以下僅介紹命令列的操作方式。
SQLite顧名思議是以SQL為基礎的資料庫軟體,SQL是一套強大的資料庫語言,主要概念是由「資料庫」、「資料表」(table)、「查詢指令」(queries)等單元組成的「關聯性資料庫」(進一步的概念可參考網路上各種關於SQL及關聯性資料庫的文件)。因為 SQL的查詢功能強大,語法一致而入門容易,因此成為現今主流資料庫的標準語言(微軟、Oracle等大廠的資料庫軟體都提供SQL語法的查詢及操作)。
以下我們就建立資料庫、建立資料表及索引、新增資料、查詢資料、更改資料、移除資料、sqlite3命令列選項等幾個項目做簡單的介紹。
目錄
[隱藏]
* 1 建立資料庫檔案
* 2 在sqlite3提示列下操作
* 3 SQL的指令格式
* 4 建立資料表
* 5 建立索引
* 6 加入一筆資料
* 7 查詢資料
* 8 如何更改或刪除資料
* 9 其他sqlite的特別用法
* 10 小結
[編輯]
建立資料庫檔案
用sqlite3建立資料庫的方法很簡單,只要在shell下鍵入(以下$符號為shell提示號,請勿鍵入):
$ sqlite3 foo.db3
如果目錄下沒有foo.db3,sqlite3就會建立這個資料庫。sqlite3並沒有強制資料庫檔名要怎麼取,因此如果你喜歡,也可以取個例如foo.icannameitwhateverilike的檔名。
[編輯]
在sqlite3提示列下操作
kl;kjlkjljklkjkj 進入了sqlite3之後,會看到以下文字:
SQLite version 3.1.3
Enter ".help" for instructions
sqlite>
這時如果使用.help可 以取得求助,.quit則是離開(請注意:不是quit)
[編輯]
SQL的指令格式
所有的SQL指令都是以分號(;)結尾的。如果遇到兩個減號(--)則代表註解,sqlite3會略過去。
[編輯]
建立資料表
假設我們要建一個名叫film的資料表,只要鍵入以下指令就可以了:
create table film(title, length, year, starring);
這樣我們就建立了一個名叫film的資料表,裡面有name、length、year、starring四個欄位。
這個create table指令的語法為:
create table table_name(field1, field2, field3, ...);
table_name是資料表的名稱,fieldx則是欄位的名字。sqlite3與許多SQL資料庫軟體不同的是,它不在乎欄位屬於哪一種資料型態:sqlite3的欄位可以儲存任何東西:文字、數字、大量文字(blob),它會在適時自動轉換。
[編輯]
建立索引
如果資料表有相當多的資料,我們便會建立索引來加快速度。好比說:
create index film_title_index on film(title);
意思是針對film資料表的title欄位,建立一個名叫film_title_index的索引。這個指令的語法為
create index index_name on table_name(field_to_be_indexed);
一旦建立了索引,sqlite3會在針對該欄位作查詢時,自動使用該索引。這一切的操作都是在幕後自動發生的,無須使用者特別指令。
[編輯]
加入一筆資料
接下來我們要加入資料了,加入的方法為使用insert into指令,語法為:
insert into table_name values(data1, data2, data3, ...);
例如我們可以加入
insert into film values ('Silence of the Lambs, The', 118, 1991, 'Jodie Foster');
insert into film values ('Contact', 153, 1997, 'Jodie Foster');
insert into film values ('Crouching Tiger, Hidden Dragon', 120, 2000, 'Yun-Fat Chow');
insert into film values ('Hours, The', 114, 2002, 'Nicole Kidman');
如果該欄位沒有資料,我們可以填NULL。
[編輯]
查詢資料
講到這裡,我們終於要開始介紹SQL最強大的select指令了。我們首先簡單介紹select的基本句型:
select columns from table_name where expression;
最常見的用法,當然是倒出所有資料庫的內容:
select * from film;
如果資料太多了,我們或許會想限制筆數:
select * from film limit 10;
或是年份比較早的電影先列出來(預設為 asc):
select * from film order by year limit 10;
或是年份比較晚的電影先列出來:
select * from film order by year desc limit 10;
或是我們只想看電影名稱跟年份:
select title, year from film order by year desc limit 10;
查所有茱蒂佛斯特演過的電影:
select * from film where starring='Jodie Foster';
查所有演員名字開頭叫茱蒂的電影('%'、'_' 符號便是 SQL 的萬用字元,前者代表任意長度字元,後者代表任意一個字元):
select * from film where starring like 'Jodie%';
查所有演員名字以茱蒂開頭、年份晚於1985年、年份晚的優先列出、最多十筆,只列出電影名稱和年份:
select title, year from film where starring like 'Jodie%' and year >= 1985 order by year desc limit 10;
有時候我們只想知道資料庫一共有多少筆資料:
select count(*) from film;
有時候我們只想知道1985年以後的電影有幾部:
select count(*) from film where year >= 1985;
(進一步的各種組合,要去看SQL專書,不過你大概已經知道SQL為什麼這麼流行了:這種語言允許你將各種查詢條件組合在一起──而我們還沒提到「跨資料庫的聯合查詢」呢!)
[編輯]
如何更改或刪除資料
瞭解select的用法非常重要,因為要在sqlite更改或刪除一筆資料,也是靠同樣的語法。
例如有一筆資料的名字打錯了:
update film set starring='Jodie Foster' where starring='Jodee Foster';
就會把主角欄位裡,被打成'Jodee Foster'的那筆(或多筆)資料,改回成Jodie Foster。
delete from film where year > 1970;
就會刪除所有年代早於1970年(不含)的電影了。
[編輯]
其他sqlite的特別用法
sqlite可以在shell底下直接執行命令:
sqlite3 film.db "select * from film;"
輸出 HTML 表格:
sqlite3 -html film.db "select * from film;"
將資料庫「倒出來」:
sqlite3 film.db ".dump" > output.sql
利用輸出的資料,建立一個一模一樣的資料庫(加上以上指令,就是標準的SQL資料庫備份了):
sqlite3 film.db < output.sql
在大量插入資料時,你可能會需要先打這個指令:
begin;
插入完資料後要記得打這個指令,資料才會寫進資料庫中:
commit;
[編輯]
小結
以上我們介紹了SQLite這套資料庫系統的用法。事實上OS X也有諸於SQLiteManagerX這類的圖形介面程式,可以便利資料庫的操作。不過萬變不離其宗,瞭解SQL指令操作,SQLite與其各家變種就很容易上手了。
至於為什麼要寫這篇教學呢?除了因為OS X Tiger大量使用SQLite之外(例如:Safari的RSS reader,就是把文章存在SQLite資料庫裡!你可以開開看~/Library/Syndication/Database3這個檔案,看看裡面有什麼料),OpenVanilla從0.7.2開始,也引進了以SQLite為基礎的詞彙管理工具,以及全字庫的注音輸入法。因為使用SQLite,這兩個模組不管資料庫內有多少筆資料,都可以做到「瞬間啟動」以及相當快速的查詢回應。
將一套方便好用的資料庫軟體包進OS X中,當然也算是Apple相當相當聰明的選擇。再勤勞一點的朋友也許已經開始想拿SQLite來記錄各種東西(像我們其中就有一人寫了個程式,自動記錄電池狀態,寫進SQLite資料庫中再做統計......)了。想像空間可說相當寬廣。
目前支援SQLite的程式語言,你能想到的大概都有了。這套資料庫2005年還贏得了美國O'Reilly Open Source Conference的最佳開放原始碼軟體獎,獎評是「有什麼東西能讓Perl, Python, PHP, Ruby語言團結一致地支援的?就是SQLite」。由此可見SQLite的地位了。而SQLite程式非常小,更是少數打 "gcc -o sqlite3 *",不需任何特殊設定就能跨平臺編譯的程式。小而省,小而美,SQLite連網站都不多贅言,直指SQL語法精要及API使用方法,原作者大概也可以算是某種程式設計之道(Tao of Programming)裡所說的至人了。
--
OS X自從10.4後把SQLite這套相當出名的資料庫軟體,放進了作業系統工具集裡。OS X包裝的是第三版的SQLite,又稱SQLite3。這套軟體有幾個特色:
* 軟體屬於公共財(public domain),SQLite可說是某種「美德軟體」(virtueware),作者本人放棄著作權,而給使用SQLite的人以下的「祝福」(blessing):
o May you do good and not evil. 願你行善莫行惡
o May you find forgiveness for yourself and forgive others. 願你原諒自己寬恕他人
o May you share freely, never taking more than you give. 願你寬心與人分享,所取不多於你所施予
* 支援大多數的SQL指令(下面會簡單介紹)。
* 一個檔案就是一個資料庫。不需要安裝資料庫伺服器軟體。
* 完整的Unicode支援(因此沒有跨語系的問題)。
* 速度很快。
目前在OS X 10.4裡,SQLite是以/usr/bin/sqlite3的形式包裝,也就說這是一個命令列工具,必須先從終端機(Terminal.app或其他程式)進入shell之後才能使用。網路上有一些協助使用SQLite的視覺化工具,但似乎都沒有像CocoaMySQL(配合MySQL資料庫使用)那般好用。或許隨時有驚喜也未可知,以下僅介紹命令列的操作方式。
SQLite顧名思議是以SQL為基礎的資料庫軟體,SQL是一套強大的資料庫語言,主要概念是由「資料庫」、「資料表」(table)、「查詢指令」(queries)等單元組成的「關聯性資料庫」(進一步的概念可參考網路上各種關於SQL及關聯性資料庫的文件)。因為 SQL的查詢功能強大,語法一致而入門容易,因此成為現今主流資料庫的標準語言(微軟、Oracle等大廠的資料庫軟體都提供SQL語法的查詢及操作)。
以下我們就建立資料庫、建立資料表及索引、新增資料、查詢資料、更改資料、移除資料、sqlite3命令列選項等幾個項目做簡單的介紹。
目錄
[隱藏]
* 1 建立資料庫檔案
* 2 在sqlite3提示列下操作
* 3 SQL的指令格式
* 4 建立資料表
* 5 建立索引
* 6 加入一筆資料
* 7 查詢資料
* 8 如何更改或刪除資料
* 9 其他sqlite的特別用法
* 10 小結
[編輯]
建立資料庫檔案
用sqlite3建立資料庫的方法很簡單,只要在shell下鍵入(以下$符號為shell提示號,請勿鍵入):
$ sqlite3 foo.db3
如果目錄下沒有foo.db3,sqlite3就會建立這個資料庫。sqlite3並沒有強制資料庫檔名要怎麼取,因此如果你喜歡,也可以取個例如foo.icannameitwhateverilike的檔名。
[編輯]
在sqlite3提示列下操作
kl;kjlkjljklkjkj 進入了sqlite3之後,會看到以下文字:
SQLite version 3.1.3
Enter ".help" for instructions
sqlite>
這時如果使用.help可 以取得求助,.quit則是離開(請注意:不是quit)
[編輯]
SQL的指令格式
所有的SQL指令都是以分號(;)結尾的。如果遇到兩個減號(--)則代表註解,sqlite3會略過去。
[編輯]
建立資料表
假設我們要建一個名叫film的資料表,只要鍵入以下指令就可以了:
create table film(title, length, year, starring);
這樣我們就建立了一個名叫film的資料表,裡面有name、length、year、starring四個欄位。
這個create table指令的語法為:
create table table_name(field1, field2, field3, ...);
table_name是資料表的名稱,fieldx則是欄位的名字。sqlite3與許多SQL資料庫軟體不同的是,它不在乎欄位屬於哪一種資料型態:sqlite3的欄位可以儲存任何東西:文字、數字、大量文字(blob),它會在適時自動轉換。
[編輯]
建立索引
如果資料表有相當多的資料,我們便會建立索引來加快速度。好比說:
create index film_title_index on film(title);
意思是針對film資料表的title欄位,建立一個名叫film_title_index的索引。這個指令的語法為
create index index_name on table_name(field_to_be_indexed);
一旦建立了索引,sqlite3會在針對該欄位作查詢時,自動使用該索引。這一切的操作都是在幕後自動發生的,無須使用者特別指令。
[編輯]
加入一筆資料
接下來我們要加入資料了,加入的方法為使用insert into指令,語法為:
insert into table_name values(data1, data2, data3, ...);
例如我們可以加入
insert into film values ('Silence of the Lambs, The', 118, 1991, 'Jodie Foster');
insert into film values ('Contact', 153, 1997, 'Jodie Foster');
insert into film values ('Crouching Tiger, Hidden Dragon', 120, 2000, 'Yun-Fat Chow');
insert into film values ('Hours, The', 114, 2002, 'Nicole Kidman');
如果該欄位沒有資料,我們可以填NULL。
[編輯]
查詢資料
講到這裡,我們終於要開始介紹SQL最強大的select指令了。我們首先簡單介紹select的基本句型:
select columns from table_name where expression;
最常見的用法,當然是倒出所有資料庫的內容:
select * from film;
如果資料太多了,我們或許會想限制筆數:
select * from film limit 10;
或是年份比較早的電影先列出來(預設為 asc):
select * from film order by year limit 10;
或是年份比較晚的電影先列出來:
select * from film order by year desc limit 10;
或是我們只想看電影名稱跟年份:
select title, year from film order by year desc limit 10;
查所有茱蒂佛斯特演過的電影:
select * from film where starring='Jodie Foster';
查所有演員名字開頭叫茱蒂的電影('%'、'_' 符號便是 SQL 的萬用字元,前者代表任意長度字元,後者代表任意一個字元):
select * from film where starring like 'Jodie%';
查所有演員名字以茱蒂開頭、年份晚於1985年、年份晚的優先列出、最多十筆,只列出電影名稱和年份:
select title, year from film where starring like 'Jodie%' and year >= 1985 order by year desc limit 10;
有時候我們只想知道資料庫一共有多少筆資料:
select count(*) from film;
有時候我們只想知道1985年以後的電影有幾部:
select count(*) from film where year >= 1985;
(進一步的各種組合,要去看SQL專書,不過你大概已經知道SQL為什麼這麼流行了:這種語言允許你將各種查詢條件組合在一起──而我們還沒提到「跨資料庫的聯合查詢」呢!)
[編輯]
如何更改或刪除資料
瞭解select的用法非常重要,因為要在sqlite更改或刪除一筆資料,也是靠同樣的語法。
例如有一筆資料的名字打錯了:
update film set starring='Jodie Foster' where starring='Jodee Foster';
就會把主角欄位裡,被打成'Jodee Foster'的那筆(或多筆)資料,改回成Jodie Foster。
delete from film where year > 1970;
就會刪除所有年代早於1970年(不含)的電影了。
[編輯]
其他sqlite的特別用法
sqlite可以在shell底下直接執行命令:
sqlite3 film.db "select * from film;"
輸出 HTML 表格:
sqlite3 -html film.db "select * from film;"
將資料庫「倒出來」:
sqlite3 film.db ".dump" > output.sql
利用輸出的資料,建立一個一模一樣的資料庫(加上以上指令,就是標準的SQL資料庫備份了):
sqlite3 film.db < output.sql
在大量插入資料時,你可能會需要先打這個指令:
begin;
插入完資料後要記得打這個指令,資料才會寫進資料庫中:
commit;
[編輯]
小結
以上我們介紹了SQLite這套資料庫系統的用法。事實上OS X也有諸於SQLiteManagerX這類的圖形介面程式,可以便利資料庫的操作。不過萬變不離其宗,瞭解SQL指令操作,SQLite與其各家變種就很容易上手了。
至於為什麼要寫這篇教學呢?除了因為OS X Tiger大量使用SQLite之外(例如:Safari的RSS reader,就是把文章存在SQLite資料庫裡!你可以開開看~/Library/Syndication/Database3這個檔案,看看裡面有什麼料),OpenVanilla從0.7.2開始,也引進了以SQLite為基礎的詞彙管理工具,以及全字庫的注音輸入法。因為使用SQLite,這兩個模組不管資料庫內有多少筆資料,都可以做到「瞬間啟動」以及相當快速的查詢回應。
將一套方便好用的資料庫軟體包進OS X中,當然也算是Apple相當相當聰明的選擇。再勤勞一點的朋友也許已經開始想拿SQLite來記錄各種東西(像我們其中就有一人寫了個程式,自動記錄電池狀態,寫進SQLite資料庫中再做統計......)了。想像空間可說相當寬廣。
目前支援SQLite的程式語言,你能想到的大概都有了。這套資料庫2005年還贏得了美國O'Reilly Open Source Conference的最佳開放原始碼軟體獎,獎評是「有什麼東西能讓Perl, Python, PHP, Ruby語言團結一致地支援的?就是SQLite」。由此可見SQLite的地位了。而SQLite程式非常小,更是少數打 "gcc -o sqlite3 *",不需任何特殊設定就能跨平臺編譯的程式。小而省,小而美,SQLite連網站都不多贅言,直指SQL語法精要及API使用方法,原作者大概也可以算是某種程式設計之道(Tao of Programming)裡所說的至人了。
SQLite問題集
如何創建自增字段?
SQLite 支持哪些數據類型?
為什麼能向 SQLite 數據庫的整型字段中插入字符串?
為什麼 SQLite 認為表達式 '0'=='00' 為真?
為什麼 SQLite 不允許在同一張表裡使用 '0' 和 '0.0' 作為兩個不同的行的主鍵?
為什麼不能在 Linux box 中讀取在 SparcStation 中創建的 SQLite 數據庫?
多個應用程序或者同一個應用程序的多個例程能同時存取同一個數據庫文件嗎?
SQLite是線程安全的嗎?
如何列出一個 SQLite 數據庫中的所有的表/索引?
SQLite數據庫是否有已知的大小限制?
在 SQLite 中 VARCHAR 的最大長度是多少?
SQLite 是否支持 BLOB 類型?
如何從一個已存在的 SQLite 數據表中添加/刪除字段?
我刪除了很多數據但是數據庫文件並沒有減小,是不是 Bug?
是否能將 SQLite 用於商業用途而不用交版權費用?
我如何使用含有單引號(')的字符串?
SQLITE_SCHEMA 錯誤代表什麼?
為什麼ROUND(9.95,1) 返回 9.9 而不是 10.0? 難道9.95 不該向上進位麼?
(1) 如何創建自增字段?
簡單的回答:一個聲明為 INTEGER PRIMARY KEY 的字段將自動增加。
這裡是詳細的答案: 從 SQLite 的 2.3.4 版本開始,如果你將一個表中的一個字段聲明為 INTEGER PRIMARY KEY,那麼無論你何時向該表的該字段插入一個 NULL 值,這個 NULL 值將自動被更換為比表中該字段所有行的最大值大 1 的整數;如果表為空,那麼將被更換為 1。比如,假設你有這樣的一張數據表:
CREATE TABLE t1(
a INTEGER PRIMARY KEY,
b INTEGER
);
在這張數據表裡,聲明
INSERT INTO t1 valueS(NULL,123);
在邏輯意義上等價於:
INSERT INTO t1 valueS((SELECT max(a) FROM t1)+1,123);
一個新的API函數 sqlite3_last_insert_rowid() 返回最近的插入操作的整形鍵
注意這個整型鍵始終比之前插入表中的最後一個鍵大1。新鍵相對於表中的已有鍵來說是唯一的, 但它可能與之前從表中刪除的鍵值重疊。要始終得到在整個表中唯一的鍵,在INTEGER PRIMARY KEY的聲明之前加關鍵詞AUTOINCREMENT.這樣被選的鍵將總是比表中已存在的最大鍵大1。若可能的 最大鍵已存在於表中,INSERT操作將失敗並返回一個SQLITE_FULL錯誤碼.
(2) SQLite 支持哪些數據類型?
參見 http://www.sqlite.org/datatype3.html.
(3) 為什麼能向 SQLite 數據庫的整型字段中插入字符串?
這是一個功能,不是一個 bug。你可以在任何字段中放任何信息,而不用管字段聲明為什麼類型。 你可以往整型字段中插入任意長度的字符串,或者往布爾字段中插入浮點數,或者往字符字段中 插入日期。在 CREATE TABLE 命令中你指定給這個字段的數據類型不會限制插入這個字段的數據。 所有的字段可以插入任意長度的字符串。但對於 INTEGER PRIMARY KEY 字段例外。這種字段只能 存放一個64位的整數,否則會出錯。
但SQLite會默認你希望使用聲明的字段類型。所以,比如你希望在一個聲明為INTEGER的字段 中插入一個字符串,SQLite會試圖將其轉換為一個整數。如果轉換成功,那麼整數將被插入,否 則插入字符串,這種特性有時被稱作type or column affinity.
(4) 為什麼 SQLite 認為表達式 '0'=='00' 為真?
在 2.7.0 之後,表達式不成立。參見文檔 datatypes in SQLite version 3
(5) 為什麼 SQLite 不允許在同一張表裡使用 '0' 和 '0.0' 作為兩個不同的行的主鍵?
你的主鍵一定是數值類型的,把類型改為 TEXT 就可以了。
每一行必須有一個唯一的主鍵。作為一個數字類型的字段,SQLite 認為 '0' 和 '0.0'的值是相同的, 因為他們在數字上的比較是相等的(看前面的問題)因此值不是唯一的。
(6) 為什麼不能在 Linux box 中讀取在 SparcStation 中創建的 SQLite 數據庫?
你需要升級你的 SQLite 庫到 2.6.3 或更新版本。
x86 處理器是 little-endian 型的而 Sparc 是 big-endian 型的。新版本的 SQLite 解決了這個問題。
註: big endian和little endian是CPU處理多字節數的不同方式。例如「漢」字的Unicode編碼是6C49。那麼寫到文件裡時,究竟是將6C寫在前面,還是將49寫在前面?如果將6C寫在前面,就是big endian。還是將49寫在前面,就是little endian。
(7) 多個應用程序或者同一個應用程序的多個例程能同時存取同一個數據庫文件嗎?
多進程可以同時打開同一個數據庫,也可以同時 SELECT 。但只有一個進程可以立即改數據庫。
SQLite使用讀/寫鎖定來控制數據庫訪問。(Win95/98/ME 操作系統缺乏讀/寫鎖定支持,在低於 2.7.0 的版本中,這意味著在 windows 下在同一時間內只能有一個進程讀數據庫。在版本 2.7.0 中 這個問題通過在 windows 接口代碼中執行一個用戶間隔幾率讀寫鎖定策略解決了。) 但如果數據庫文件在一個 NFS 文件系統中,控制並發讀書的鎖定機制可以會出錯。因為 NFS 的fcntl() 文件鎖定有時會出問題。如果有多進程可能並發讀數據庫則因當避免把數據庫文件放在 NFS 文件系統中。 根據微軟的文檔,如果不運行 Share.exe 後台程序則 FAT 文件系統中的鎖定可能不工作。對 Windows 非常有經驗的人告訴我網絡文件的鎖定有許多問題並且不可靠。如果是這樣,在2個或以上 Windows 系統中共享一個 SQLite 數據庫文件會導致不可預知的問題。
我們知道沒有其他的嵌入式 SQL數據庫引擎比SQLite支持更多的並發性。 SQLite允許多進程 同時打開和讀取數據庫。任何一個進程需要寫入時,整個數據庫將在這一過程中被鎖定。但這一般僅耗時 幾毫秒。其他進程只需等待然後繼續其他事務。其他嵌入式SQL數據庫引擎往往只允許單進程訪問數據庫。
但是,client/server型的數據庫引擎 (如 PostgreSQL, MySQL, 以及 Oracle) 通常支持更高的並發度, 並支持多進程同時寫入同一個數據庫。由於總有一個控制良好的服務器協調數據庫的訪問,這才保證了以上 特性的實現。如果你的應用需要很高的並發度,你應該考慮使用client/server數據庫。事實上,經驗告訴 我們大多數應用所需要的並發度比他們的設計者們想像的要少得多。
當 SQLite 嘗試操作一個被另一個進程鎖定的文件時,缺省的行為是返回 SQLITE_BUSY。你可以用 C代碼更改這一行為。 使用 sqlite3_busy_handler() 或sqlite3_busy_timeout() API函數。
如果兩個或更多進程同時打開同一個數據庫,其中一個進程創建了新的表或索引,則其它進程可能不能立即看見新的表。其它進程可能需要關閉並重新連結數據庫。
(8) SQLite是線程安全的嗎?
有時候是的。為了線程安全,SQLite 必須在編譯時把 THREADSAFE 預處理宏設為1。在缺省的發行的已編譯版本中 Windows 版的是線程安全的,而 Linux 版的不是。如果要求線程安全,Linux 版的要重新編譯。
「線程安全」是指二個或三個線程可以同時調用獨立的不同的sqlite3_open() 返回的"sqlite3"結構。而不是在多線程中同時使用同一個 sqlite3 結構指針。
一個sqlite3結構只能在調用 sqlite3_open創建它的那個進程中使用。你不能在一個線程中打開一個數據庫然後把指針傳遞給另一個線程使用。這是因為大多數多線程系統的限制(或 Bugs?)例如RedHat9上。在這些有問題的系統上,一個 線程創建的fcntl()鎖不能由另一個線程刪除或修改。由於SQLite依賴fcntl()鎖來進行並發控制,當在線程間傳遞數據庫連接時會出現嚴重的問題。
也許在Linux下有辦法解決fcntl()鎖的問題,但那十分複雜並且對於正確性的測試將是極度困難的。因此,SQLite目前不允許在線程間共享句柄。
在UNIX下,你不能通過一個 fork() 系統調用把一個打開的 SQLite 數據庫放入子過程中,否則會出錯。
(9) 如何列出一個 SQLite 數據庫中的所有的表/索引?
在sqlite3 命令行程序中你可以用命令 ".tables" 來顯示所有的表或者用 ".schema"來顯示所有的表結構和索引。但命令後不要跟 LIKE 語句,否則會限製表的顯示。
在 C/C++ 程序中 (或使用 Tcl/Ruby/Perl/Python綁定的腳本中)你可以通過訪問名為"SQLITE_MASTER的表來實現。每個 SQLite 數據庫有一個 SQLITE_MASTER 表,表內有數據庫的結構。SQLITE_MASTER表是這樣的:
CREATE TABLE sqlite_master (
type TEXT,
name TEXT,
tbl_name TEXT,
rootpage INTEGER,
sql TEXT
);
對於表來說,type字段的值為'table',name 字段是表的名稱。使用以下語句可以等到所有表的列表:
SELECT name FROM sqlite_master
WHERE type='table'
ORDER BY name;
對於索引來說, type = 'index', name 是索引的名稱, tbl_name 是索引所屬的表的名稱。對於表和索引,sql 字段是創建表或索引的原始語句文本。對於自動創建的索引(一般是使用 PRIMARY KEY 或 UNIQUE 創建的),sql字段為 NULL.
SQLITE_MASTER表是只讀的。你不能對該表使用 UPDATE, INSERT, 或 DELETE。該表自動由 CREATE TABLE, CREATE INDEX, DROP TABLE 和 DROP INDEX 命令更新。
臨時表及其索引不在 SQLITE_MASTER 表中而在 SQLITE_TEMP_MASTER 中出現。SQLITE_TEMP_MASTER 與 SQLITE_MASTER 表一樣工作,但只對於創建臨時表的程序可見。要得到所在表包括臨時表可以使用如下命令:
SELECT name FROM
(SELECT * FROM sqlite_master UNION ALL
SELECT * FROM sqlite_temp_master)
WHERE type='table'
ORDER BY name
(10) SQLite數據庫是否有已知的大小限制?
數據庫大小被限制在 2TB(241 bytes). 這是理論限制。事實上,你應該把 SQLite數據庫的大小限制在100GB以下,以免出現運行性能上的問題。如果你需要儲存100GB或更多數據在一個數據庫中, 考慮使用為此而設計的企業版數據庫吧。
一個數據庫的理論行數限制是 264-1,顯然你會在達到行數限制之前先超過文件大小的限制。目前一行可以存放 230 bytes 數據。而基本的文件格式可以支持行大小到約 262 bytes.
可能還會有對於表、索引的數目或表和索引中的字段數的限制,但沒人知道是多少。事實上,每當新數據庫打開時,SQLite需要讀取和 分析所有表和索引聲明的初始SQL,所以,為了調用 sqlite3_open() 時獲得最佳性能,最好減少聲明的表的數目。同樣的,即使 對於表中字段數沒有限制,多於100個也顯得太多了。 只有表開頭的31個字段會得到優化。你可以在一個索引中放入任意多的字段但超過30字段的索引將不用於優化查詢。
表,索引,視圖,觸發器和字段名稱可以任意長,但SQL 函數名 (由 sqlite3_create_function() API創建的)不得超過255個字符。
(11) 在 SQLite 中 VARCHAR 的最大長度是多少?
SQLite不強制VARCHAR的長度。你可以聲明一個VARCHAR(10),SQLite一樣可以讓你存放500個字符在裡面。 並且它們會始終完整無缺——決不會被截斷。
(12) SQLite 是否支持 BLOB 類型?
SQLite 3.0 版支持在任何字段存放 BLOB 數據,不管字段聲明為什麼類型。
(13) 如何從一個已存在的 SQLite 數據表中添加/刪除字段?
SQLite有有限的ALTER TABLE支持,可以用於添加字段到表的末尾 或更改表名。如果你要對表的結構作更複雜的修改,你需要重新創建表。你可以在一個臨時表中備份數據,撤銷舊表,重建新表後再恢復數據。
例如,假設你有一個名為 "t1" 的表,有名為 "a", "b", 和 "c" 三個字段,你要刪除字段 "c" 。可按如下步驟操作:
BEGIN TRANSACTION;
CREATE TEMPORARY TABLE t1_backup(a,b);
INSERT INTO t1_backup SELECT a,b FROM t1;
DROP TABLE t1;
CREATE TABLE t1(a,b);
INSERT INTO t1 SELECT a,b FROM t1_backup;
DROP TABLE t1_backup;
COMMIT;
(14) 我刪除了很多數據但是數據庫文件並沒有減小,是不是 Bug?
不是的。當你從 SQLite 刪除數據之後,未使用的磁盤空間被添加到一個內在的「空閒列表」中用於存儲你下次插入的數據。磁盤空間並沒有丟失,但是也不向操作系統返回磁盤空間。
如果你刪除了大量的數據且想要減小數據庫文件,執行 VACUUM命令。VACUUM 命令會清空「空閒列表」,把數據庫尺寸縮到最小。注意, VACUUM 會耗費一些時間(在 Linux 系統下大約0.5秒/兆)並且要使用兩倍於數據庫文件大小的磁盤空間。
對於SQLite version 3.1, 替代VACUUM命令的一個方法是auto-vacuum模式,用 auto_vacuum pragma語法開啟該模式。
(15) 是否能將 SQLite 用於商業用途而不用交版權費用?
可以。SQLite 是公開的。代碼的任何部分都沒有聲明所有權。你可以用它來做你想要的任何事情。
(16) 如何插入有單引號(')的字符串?
使用雙單引號即可,例如:
INSERT INTO xyz valueS('5 O''clock');
插入數據庫的是:5 0'clock。
(17) SQLITE_SCHEMA 錯誤代表什麼?
在 SQLite 版本3中,當一個預處理 SQL 語句不合法不能執行時就會返回一個 SQLITE_SCHEMA 錯誤。當這個錯誤發生時,該語句應當用 sqlite3_prepare() API函數重新編譯。在 SQLite 版本3中,只有使用 sqlite3_prepare()/sqlite3_step()/sqlite3_finalize() API函數執行 SQL 才會發生這個錯誤,而使用 sqlite3_exec(). 則不會。這與版本2不同。
大部分發生這個錯誤的原因是當 SQL 預處理完時數據庫已經改變了(可能是被另一個進程改變的)。還可能有如下原因:
對一個數據庫進行DETACH操作
對一個數據庫進行VACUUM操作
一個用戶函數定義被刪除或改變了
一個排序定義被刪除或改變了
一個授權函數改變了
解決的辦法是重新編譯並再次嘗試執行。所有涉及 sqlite3_prepare()/sqlite3_step()/sqlite3_finalize() API 函數的都應當重新編譯。參見下例:
int rc;
sqlite3_stmt *pStmt;
char zSql[] = "SELECT .....";
do {
/* Compile the statement from SQL. Assume success. */
sqlite3_prepare(pDb, zSql, -1, &pStmt, 0);
while( SQLITE_ROW==sqlite3_step(pStmt) ){
/* Do something with the row of available data */
}
/* Finalize the statement. If an SQLITE_SCHEMA error has
** occured, then the above call to sqlite3_step() will have
** returned SQLITE_ERROR. sqlite3_finalize() will return
** SQLITE_SCHEMA. In this case the loop will execute again.
*/
rc = sqlite3_finalize(pStmt);
} while( rc==SQLITE_SCHEMA );
(18) 為什麼ROUND(9.95,1) 返回 9.9 而不是 10.0? 難道9.95 不該向上進位麼?
SQLite 內部使用二進制運算,9.95用 64-bit IEEE 浮點數 ( SQLite 內部使用的) 表示為9.949999999999999289457264239899814128875732421875。所以當你輸入 "9.95"時,SQLite 就理解為上述的數字,進而四捨五入得到9.9。這個問題在處理浮點二進制數總會產生。通常的規則是十進制的有限浮點數通常無法表示為二進制有限浮點數,只能由最接近的二進制數來代替。這個近似數會非常接近原數,但總一些細微的不同,所以可能無法得到你預期的結果。
Connecting SQLite with VB.net
引用來源
--
Imports System.Data
Imports System.Data.SQLite
Public Class frmDB
Dim cons As New SQLite.SQLiteConnection
Dim cmd As New SQLite.SQLiteCommand
Dim sql As String
Dim strSQL As String
Dim dss As New DataSet
Dim das As New SQLite.SQLiteDataAdapter
Private Sub btnLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLoad.Click
SQLiteConnection.CreateFile("C:\SQLite_VB.net_Test\mydatabase.db")
cons.ConnectionString = "Data Source=C:\SQLite_VB.net_Test\mydatabase.db; Version=3"
strSQL = "create table Ramya(Elename varchar(50))"
cons.Open()
das = New SQLite.SQLiteDataAdapter(strSQL, cons)
das.Fill(dss, "ramya")
cons.Close()
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
cons.ConnectionString = "Data Source=C:\SQLite_VB.net_Test\mydatabase.db; Version=3"
cons.Open()
cmd = cons.CreateCommand()
cmd.CommandText = "INSERT INTO Ramya VALUES('Microsoft')"
cmd.CommandType = CommandType.Text
cmd.ExecuteNonQuery()
cmd.Dispose()
cons.Close()
MsgBox("New record added to the database")
End Sub
End Class
--
Imports System.Data
Imports System.Data.SQLite
Public Class frmDB
Dim cons As New SQLite.SQLiteConnection
Dim cmd As New SQLite.SQLiteCommand
Dim sql As String
Dim strSQL As String
Dim dss As New DataSet
Dim das As New SQLite.SQLiteDataAdapter
Private Sub btnLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLoad.Click
SQLiteConnection.CreateFile("C:\SQLite_VB.net_Test\mydatabase.db")
cons.ConnectionString = "Data Source=C:\SQLite_VB.net_Test\mydatabase.db; Version=3"
strSQL = "create table Ramya(Elename varchar(50))"
cons.Open()
das = New SQLite.SQLiteDataAdapter(strSQL, cons)
das.Fill(dss, "ramya")
cons.Close()
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
cons.ConnectionString = "Data Source=C:\SQLite_VB.net_Test\mydatabase.db; Version=3"
cons.Open()
cmd = cons.CreateCommand()
cmd.CommandText = "INSERT INTO Ramya VALUES('Microsoft')"
cmd.CommandType = CommandType.Text
cmd.ExecuteNonQuery()
cmd.Dispose()
cons.Close()
MsgBox("New record added to the database")
End Sub
End Class
訂閱:
文章 (Atom)