1,數據庫
1)概念
數據庫是長期存儲在計算機內、有組織的、可共享的大量數據的集合。
2)特點
①數據庫數據特點
永久存儲、有組織、可共享。
(數據的最小存取單位是數據項)
②數據庫系統的特點
數據結構化
數據的共享性,冗餘度,易擴充
數據獨立性高
邏輯數據獨立性(logical data independence)是指概念模式改變,外模式和應用程序不變。
在邏輯數據獨立性裏,數據的邏輯結構發生改變或存儲關係的選擇發生改變時用戶不會受到影響。改變概念模式,例如增加和刪除實體、增加和刪除屬性、增加和刪除聯繫,不需要改變現有的外模式或重寫應用程序。在DBMS中只需要修改視圖的定義和映像來支持邏輯數據獨立性。對用戶來說,不再關心所做的修改是非常重要的。換句話說,模式經過邏輯重構之後,根據外模式構建的應用程序還是和從前一樣工作。
3)數據庫連接
java應用程序可以通過JDBC或Hibernate對數據庫系統進行訪問。JDBC或Hibernate提供了事務控制的接口,這些接口把事務控制相關的命令發送給數據庫系統,由數據庫系統來控制事務的隔離級別。
①Hibernate
Hibernate是一個開放源代碼的對象關係映射框架,它對JDBC進行了非常輕量級的對象封裝,使java程序員可以隨心所欲地使用對象編程思想來操縱數據庫。
②JDBC(Java Data Base Connectivity,java數據庫連接)
是一種用於執行SQL語句的Java API,可以爲多種關係數據庫提供統一訪問,它由一組用Java語言編寫的類和接口組成。
config.properties配置文件
mysql連接
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/hadoop?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=root
//hadoop爲數據庫名。
driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
url=jdbc\:sqlserver\://202.200.102.1\:6666;databaseName\=IMAGE_VIDEO_DEMO;
username=sa
password=123456
③事務隔離級別
事務隔離級別由數據庫系統實現。
在標準SQL規範中,定義了4個事務隔離級別。
①未授權讀取(讀未提交read uncommitted)
②授權讀取(讀提交read committed)
③可重複讀取(repeatable read)
④序列化(serializable)
4)數據庫安全–SQL注入
SQL執行時,2種方式:
①字符串處理(拼接),然後執行SQL
用戶輸入的時候,可以通過輸入sql語句來進行SQL注入。
②傳參,執行SQL –>交給SQL引擎(推薦)
5)範式
各個範式聯繫:
5NF⊂4NF⊂BCNF⊂3NF⊂2NF⊂1NF
①1NF(滿足最低要求的範式)
如果一個關係模式R的所以屬性都是不可分的基本數據項,則R∈1NF
②2NF
若R∈1NF,且每一個非主屬性完全函數依賴於碼,則R∈2NF
③3NF
若R∈3NF,則每一個非主屬性既不部分依賴於碼,也不傳遞依賴於碼。
④BCNF(修正第三範式、擴充第三範式)
所有非主屬性對每一個碼都是完全函數依賴;
所有主屬性對每一個不包含它的碼,也是完全函數依賴;
沒有任何屬性完全函數依賴於非碼的任何一組屬性。
⑤4NF
關係模式R
6)數據類型
①uniqueidentifier
可存儲16字節的二進制值,其作用與全局唯一標記符(GUID)一樣。GUID是唯一的二進制數:世界上的任何兩臺計算機都不會生成重複的GUID值。GUID主要用於在用於多個節點,多臺計算機的網絡中,分配必須具有唯一性的標識符。
SQL Server
7)函數
①OBJECT_ID
A. 返回指定對象的對象 ID
USE master;
GO
SELECT OBJECT_ID(N'AdventureWorks.Production.WorkOrder') AS 'Object ID';
GO
B. 驗證對象是否存在
USE AdventureWorks;
GO
IF OBJECT_ID (N'dbo.AWBuildVersion', N'U') IS NOT NULL
DROP TABLE dbo.AWBuildVersion;
GO
N是顯式的將非unicode字符轉成unicode字符,它來自 SQL-92 標準中的 National(Unicode)數據類型,用於擴展和標準化,在這裏可以不用,寫作object_id(PerPersonData)。
8)數據庫命名
①加中括號
列名、表名、存儲過程名、函數名等都可以按需要加中括號。防止某些關鍵字在應用中引起歧義。
select [select] from 表名;
9)鎖
①共享鎖(S鎖、讀鎖)
(讀取)操作創建的鎖。其他用戶可以併發讀取數據,但任何事物都不能獲取數據上的排它鎖,直到已釋放所有共享鎖。
若事務T對數據對象A加上S鎖,則事務T只能讀A;其他事務只能再對A加S鎖,而不能加X鎖,直到T釋放A上的S鎖。這就保證了其他事務可以讀A,但在T釋放A上的S鎖之前不能對A做任何修改。
②排它鎖(X鎖、寫鎖,eXclusive lock)
若事物T對數據對象A加上X鎖,則只允許T讀取和修改A,其它任何事務都不能再對A加任何類型的鎖,直到T釋放A上的鎖。它防止任何其它事務獲取資源上的鎖,直到在事務的末尾將資源上的原始鎖釋放爲止。
2,SQL
1)基本對象
關係數據庫系統支持 三級模式結構,其模式、外模式和內模式中的基本對象有表、視圖和索引。
①模式(schema)
A.概念
用於區分一個 大項目中的各個小項目,這樣若有相同名字的表的話, 不同模式不會發生衝突。相當於編程時的命名空間。
如:
一個公司的系統,分2個子系統,分別爲財務系統和人力資源系統.
這2個子系統, 共用一個數據庫。
那麼 財務系統的表, 可以放在財務的模式(schema).
人力資源系統的表,放在人力資源系統的模式裏面。
這2個子系統,能夠互相訪問對方的表。
但是又不因爲 表重名 的問題,影響對方。
B.訪問
訪問具體的一個表,可以由 4個部分組成
分別爲 服務器名, 數據庫名,模式名,表名。
對於訪問本地的數據庫:
不指定模式名的話, 數據庫默認使用dbo模式。
(DBO是每個數據庫的默認用戶,具有所有者權限,即DbOwner )
②表
表分爲臨時表和永久表。
臨時表
臨時表存儲在tempdb中(如下),當不再使用時會自動刪除。
IF OBJECT_ID('tempdb..#ownerAnnouce') IS NOT NULL
根據進程獨立,只有進程的擁有者有表的訪問權限,其它用戶不能訪問該表;
不同的用戶進程,創建的臨時表雖然“名字”相同,但是這些表之間相互並不存在任何關係;在SQLSERVER中,通過特別的命名機制保證臨時表的進程獨立性。
臨時表有兩種類型:本地和全局。
A.本地臨時表
名稱以單個數字符號 (#) 打頭;它們僅對當前的用戶連接是可見的;當用戶從 SQL Server 實例斷開連接時被刪除。
B.全局臨時表
名稱以兩個數字符號 (##) 打頭,創建後對任何用戶都是可見的,當所有引用該表的用戶從 SQL Server 斷開連接時被刪除。
臨時表優點
真正的臨時表利用了數據庫臨時表空間,由數據庫系統自動進行維護,因此節省了表空間。並且由於臨時表空間一般利用虛擬內存,大大減少了硬盤的I/O次數,因此也提高了系統效率。
臨時表的創建
A. create table #臨時表名
B.select * into #臨時表名 from 表名(永久表或臨時表)
③視圖
A.概念
視圖是一張虛擬表,視圖的字段是自定義的,視圖只支持查詢,查詢數據來源於實體表。
B.優點
視圖可以將多個複雜關聯表提取信息,優化查詢速度。
④索引
建立索引是加快查詢速度的有效手段。用戶可以根據應用環境的需要,在基本表上建立一個或多個索引,以提供多種存取路徑,加快查找速度。
缺點:一是增加了數據庫的存儲空間,二是在插入和修改數據時要花費較多的時間(因爲索引也要隨之變動)。
優點:
第一,通過創建唯一性索引,可以保證數據庫表中每一行數據的唯一性。
第二,可以大大加快數據的檢索速度,這也是創建索引的最主要的原因。
第三,可以加速表和表之間的連接,特別是在實現數據的參考完整性方面特別有意義。
第四,在使用分組和排序子句進行數據檢索時,同樣可以顯著減少查詢中分組和排序的時間。
第五,通過使用索引,可以在查詢的過程中,使用優化隱藏器,提高系統的性能。
2)數據查詢
①查詢條件
等於:=
不等於:<>或!=
不大於:!>
空值:is null,is not null
確定集合:in,not in
確定範圍:between and,not between and
字符匹配:like,not like
%代表任意長度(可爲0)的字符串;
_(下劃線):代表任意單個字符。(漢字代表2個字符,所以一個漢字用兩個下劃線)
\爲轉義字符
②多重排序查詢:
先按字段5排序,再按字段6排序
默認爲asc:升序排列。desc:降序排序。
order by 字段5,字段6 asc
③聯表查詢
select a.title,b.type_name
from news_table as a,name_table as b
where a.type_id=b.type_id ;
select 字段1,字段2,字段3,字段4 from 表
④case when then查詢
--簡單case函數
case sex
when '1' then '男'
when '2' then '女’
else '其他' end
--case搜索函數
case when sex = '1' then '男'
when sex = '2' then '女'
else '其他' end
應用:
select (case sex
when '1' then '男'
when '2' then '女’
else '其他' end)sex from student where class = 11;
⑤其它
use test
select * from student
use test1 /*表示使用什麼數據庫*/
set ansi_nulls on
go
set quoted_identifier on
go
select top 100 * from student where no=11;/*顯示前100行*/
select name,age from student order by age desc;/*desc倒序 asc表示正序*/
select isnull(name,'無') as name,age,class from student;/*isnull之後就無列名了 用as給列重命名*/
select name,age,class,'the name is' + name as introduce from student;/*用加號形成一個自定義列*/
select * from student where name like '%麗%';/*like模糊查詢*/
select * from student where age in(21,23);/*找出所有年齡爲21、23的人*/
select * from student where age not in(21,23);
select * from student where class is not null;
select * from student where class is not null or age in(21,23);
select * from student where class is not null and age in(21,23);
select count(class)from student;/*數量 因爲使用了92標準,所以null不計入count*/
select distinct(class)from student;/*去重複,出現所有不同的內容*/
select count(distinct(class)) from student;
select avg(age) from student;/*平均數*/
select min(age) from student;
select max(age) from student;
select sum(age) from student;/*和*/
select class,avg(age) as age from student group by class order by age desc;/*對每個班級求年齡平均值*/
select class,avg(age) as age from student
group by class
having avg(age)>23 /*要求平均年齡大於23*/
LEFT(“123456789”,LEN(“數據庫”))/*分兩步運算,第一步是運算LEN函數,結果是3。第二步針對123456789這個字符從左邊開始連續取三個數
*/
###⑤SQL-92 規則
是數據庫的一個標準。以下代碼 寫在存儲過程前面,表示遵從SQL-92 規則。
SQL-92 標準要求在對空值進行等於 (=) 或不等於 (<) 比較時取值爲 FALSE。
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
即使 column_name 中包含空值,使用 WHERE column_name = NULL 的 SELECT 語句仍返回零行。
即使 column_name 中包含非空值,使用 WHERE column_name < NULL 的 SELECT 語句仍會返回零行。
SET QUOTED_IDENTIFIER ON
爲ON:標識符可以由雙引號分隔,而文字必須由單引號分隔。
爲OFF:標識符不可加引號。
3)數據更新
數據插入
insert into tableName(no,name) values('1','kate');
數據修改
update tableName set name = 'Tom' where name='kate';
update tableName set age = age + 1;
數據刪除:
刪除表中幾行:
DELETE FROM Person WHERE LastName = 'Wilson'
刪除表中所有行:
DELETE FROM table_name
3,數據庫完整性
1)實體完整性
主鍵唯一且不爲空。
2)參照完整性
不允許修改外碼
級連操作:當刪除或修改被參照表時,同時刪除或修改參照表中的不一致元祖。
3)用戶定義的完整性
4)觸發器(Trigger)
是用戶定義在關係表上的一類由事件驅動的特殊過程。一旦定義,任何用戶對標的增刪改操作均由服務器自動激活相應觸發器,在DBMS核心層進行集中的完整性控制。
4,存儲過程(Stored Procedure)
1)概念
存儲過程是一組爲了完成特定功能的SQL 語句集,存儲在數據庫中,經過第一次編譯後再次調用不需要再次編譯,用戶通過指定存儲過程的名字並給出參數(如果該存儲過程帶有參數)來執行它。
2)優點
①執行效率高
存儲過程不像解釋執行的SQL語句那樣在提出操作 請求時才進行語法分析和優化工作,它提供了服務器端快速執行SQL語句的有效途徑。
②降低了客戶機和服務器之間的通信錄
客戶機上的應用程序只要通過網絡向服務器發出存儲過程的名字和參數,就可以讓RDBMS(關係數據庫管理系統 Relational Database Management System)執行許多條的SQL語句,並執行數據處理,只有最終處理結果才返回客戶端。
③方便實施企業規則
可以把企業規則的運算程序寫成存儲過程放入數據庫服務器中,由RDBMS管理,既有利於集中控制,又能夠方便地進行維護。
當用戶規則發生變化時,只要修改存儲過程,無須修改其他應用程序。
④安全性高
可設定只有某些用戶才具有對指定存儲過程的使用權。
3)好的習慣
sql儘量放在存儲過程中。
面對大量數據,用orcle比sql server穩定。
4)場景
當一個事務涉及到多個SQL語句時或者涉及到對多個表的操作時就要考慮用存儲過程;
當在一個事務的完成需要很複雜的商業邏輯時(比如,對多個數據的操作,對多個狀態的判斷更改等)要考慮;還有就是比較複雜的統計和彙總也要考慮,但是過多的使用存儲過程會降低系統的移植性。
5)代碼
①創建
use test1
set ansi_nulls on
go
set quoted_identifier on
go
create procedure procedure_student
-- add the parameters for the stored procedure here
@gradeid int,
@gradename varchar(10) --傳入的參數
as
begin
--計算內容
end
go
②執行
exec dbo.procedure_student 1,'g'
5,mysql命令行:
##1)查看數據庫:
show databases;
2)建庫:
create database children;
3)調用數據庫
use children;
4)建表
主鍵、非空。
create table product
(
no char(10) primary key,
code char(10) not null unique,
online char(1),
bind char(1)
);
外鍵:
foreign key(no) references product(no)
5)更新
update near_log set lnt=99 where no=001;
6)插入
insert into product values('001','001','N','N');
7)刪除
delete from all_log where lnt=34.342342;
delete from all_log;
drop table user;
6,android之sqlite
##1)概念
sqlite是一款輕量級數據庫,是遵守ACID(指數據庫事務正確執行的四個基本要素的縮寫。包含:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability))的關係型數據庫管理系統。在嵌入式設備中,可能只需要幾百K的內存就夠了。
SQLite默認是打開事務的。
2)安全性
android手機root之後,就可以在/data/data/包名/database/目錄中查看sqlite數據庫。所以,對於敏感信息,應該考慮加密。
SQLite不支持加密,所以我們針對數據庫文件加密。現有兩種解決方案:
i>對數據庫中的數據進行加密
①優點:
加密速度快。
程序無須變動,只針對數據進行加密。
②缺點:
來回加密,造成處理數據緩慢。
僅對數據加密,依然可以看到數據表的sql語句,可能猜測到表的作用。
③實現:
一是:對明文數據進行加密返回密文數據
二是:對密文數據進行解密返回明文數據
ii>對數據庫文件進行加密
①優點
對整個文件進行了加密,用戶通過編輯器看不到任何有用的數據。
進行數據庫打開時,使用程序即可解密文件。
②缺點
需要修改sqlite源碼,這個工作難度比較大。
③實現(太難,本人並沒有進行實驗)
a.修改sqlite源代碼,追加對數據庫文件進行加密的功能。
b.編譯含有加密功能的程序源代碼,生成各自平臺需要使用的庫文件。
c.將加密sqlite庫文件引入各自平臺中,修改數據庫訪問層代碼。
d.進行程序的部署,測試。
3)demo
i>在AndroidManifest.xml中添加權限:
<!-- 在SDCard中創建與刪除文件權限 -->
<uses-permission android:name= />
<!-- 往SDCard寫入數據權限 -->
<uses-permission android:name= />
ii>添加繼承SQLiteOpenHelper的MyHeper類,用於創建使用數據庫。
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class MyHelper extends SQLiteOpenHelper {
private String Tag = ;
private static String DB_NAME = ; //數據庫名稱
public static String TABLE_NAME_TASK = ; //聯班任務_fra_task表名
/**super(參數1,參數2,參數3,參數4),其中參數4是代表數據庫的版本,
* 是一個大於等於1的整數,如果要修改(添加字段)表中的字段,則設置
* 一個比當前的 參數4大的整數 ,把更新的語句寫在onUpgrade(),下一次
* 調用
*/
public MyHelper(Context context) {
super(context, DB_NAME, null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
//Create table
try{
String sql = +TABLE_NAME_TASK +
+
+
+
+ ;
db.execSQL(sql); //創建表
}catch(Exception e){
LogUtil.i(Tag, + e.getMessage());
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
iii>創建DatabaseUtil進行數據庫操作。
import java.util.ArrayList;
import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.text.style.TtsSpan.DateBuilder;
/**
* task數據操作。 ①存入數據庫:每次getList的時候調用。每次刪除所有數據,插入所有內容到數據庫。
* ②刪除內容:每次存入數據庫的時候調用。刪除所有數據。private。 ③更新:沒有此功能。 ④取數據:兩種情況下調用:
* -----i>切換任務、保障等Tab且未收到服務器讓重新getList的命令。(所以只有第一次登錄才需要第一次進入taskFragment時獲取數據)
* -----ii>切換已降落(有實落)、未降落Tab. 另外,取到的數據爲列表返回。
*
* @author luo
*
*/
public class DatabaseUtil {
private String Tag = ;
private MyHelper helper;
public DatabaseUtil(Context context) {
super();
try {
context.deleteDatabase();
helper = new MyHelper(context);
} catch (Exception e) {
LogUtil.e(Tag, + e.getMessage());
}
}
/**
* 插入數據 插入數據之前,刪除所有數據
*
* @param taskList
* @return
*/
public boolean Insert(List<Task> taskList) {
SQLiteDatabase db = helper.getWritableDatabase();
try {
DeleteALL(db);
for (Task task : taskList) {
String sql = + MyHelper.TABLE_NAME_TASK
+
+
+ + + task.TaskCode
+ + + task.TaskName + + + task.TaskState + + ;
db.execSQL(sql);
}
return true;
} catch (SQLException e) {
LogUtil.i(Tag, + e.getMessage());
return false;
} finally {
db.close();
}
}
/**
* 刪除所有數據
*/
private void DeleteALL(SQLiteDatabase db) {
try {
db.execSQL( + MyHelper.TABLE_NAME_TASK);
} catch (Exception e) {
LogUtil.i(Tag, + e.getMessage());
}
}
/**
* 查詢所有數據
*/
public List<Task> queryAll() {
List<Task> list = new ArrayList<Task>();
try {
SQLiteDatabase db = helper.getReadableDatabase();
Cursor cursor = db.query(MyHelper.TABLE_NAME_TASK, null, null, null, null, null, null);
while (cursor.moveToNext()) {
Task task = new Task();
task.TaskCode = cursor.getString(cursor.getColumnIndex());
task.TaskName = cursor.getString(cursor.getColumnIndex());
task.TaskState = cursor.getString(cursor.getColumnIndex());
list.add(task);
}
db.close();
} catch (Exception e) {
LogUtil.i(Tag, + e.getMessage());
}
return list;
}
public List<Task> queryByThisActualLanding(Boolean actual) {
SQLiteDatabase db = helper.getReadableDatabase();
List<Task> list = new ArrayList<Task>();
Cursor cursor = null;
/**
* public Cursor query (String table, String[] columns, String
* selection, String[] selectionArgs,String groupBy, String
* having,String orderBy,String limit)參數如下:
* table:表名。相當於select語句from關鍵字後面的部分。如果是多表聯合查詢,可以用逗號將兩個表名分開。
* columns:要查詢出來的列名。相當於select語句select關鍵字後面的部分。
* selection:查詢條件子句,相當於select語句where關鍵字後面的部分,在條件子句允許使用佔位符“?”
* selectionArgs:對應於selection語句中佔位符的值,值在數組中的位置與佔位符在語句中的位置必須一致,否則就會有異常。
* |------在 selection 中需要嵌入字符串的地方用 ? 代替,然後在 selectionArgs
* 中依次提供各個用於替換的值就可以了. groupBy:相當於select語句group by關鍵字後面的部分
* having:相當於select語句having關鍵字後面的部分 orderBy:相當於select語句order
* by關鍵字後面的部分,如:personid desc, age asc升序;
* limit:指定偏移量和獲取的記錄數,相當於select語句limit關鍵字後面的部分。
*/
cursor = db.query(MyHelper.TABLE_NAME_TASK, new String[] { , , },
, null, null, null, );
// Cursor cursor = db.query(table, columns, selection, selectionArgs,
// groupBy, having, orderBy)
while (cursor.moveToNext()) {
Task task = new Task();
task.TaskCode = cursor.getString(cursor.getColumnIndex());
task.TaskName = cursor.getString(cursor.getColumnIndex());
task.TaskState = cursor.getString(cursor.getColumnIndex());
list.add(task);
}
db.close();
return list;
}
}
4)其它
①多條件查詢:
and連接。
②模糊查詢:
i>使用這種query方法%號前不能加’
cursor = db.query(MyHelper.TABLE_NAME_TASK,
new String[] { ,}, ,
new String[]{ + TaskName + }, null, null, null);
ii>使用這種query方法%號前必須加’
Cursor c_test = mDatabase.query(tab_name,
new String[]{tab_field02},
tab_field02+ + str[0] + , null, null, null, null);
iii>使用這種方式必須在%號前加’
String current_sql_sel = "SELECT * FROM where like '%"+str[0]+"%'
多重排序,字符串排序
cursor = db.query(MyHelper.TABLE_NAME_TASK,
new String[] { , ,}, ,
new String[]{ + TaskName+ }, null, null,
+ + TaskState.STATE2 +
+ + TaskState.STATE1 +
+
+
+ );
③SQLiteOpenHelper
通過getWriteableDatabase和getReadableDatebase()方法來對數據庫版本進行管理。