MySQL Tips

7940 ワード

1.ライブラリ間でJavaで使用しようとする問題について
public static void main(String[] args) throws Exception {
	Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1/hive", "test", "123");
	String sql = "SELECT * FROM v";
	//1
	PreparedStatement ps = c.prepareStatement(sql);
	ResultSet rs = ps.executeQuery();
	//2
	javax.sql.rowset.CachedRowSet crsi = new com.sun.rowset.CachedRowSetImpl();
	crsi.setCommand(sql);
	crsi.execute(c);
}

SUNプライベートパッケージは既に甲骨文でサポートされていないため、この実装クラスCachedRowSetImplの使用は推奨されません.
セパレータ[//2]の下の部分は、MySQL 5.1以降のバージョンでライブラリ間ビュークエリを実行するときにエラーが発生します(5.5で正しい).
Exception in thread "main"com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: SELECT command denied to user 'test'@'127.0.0.1' for table 'v'
どうして標準的なStatementで間違いを報告しないで、SUNの遺品で間違いを報告しますか?ユーザーtestはビューvをクエリーする権限がありませんか?
2.MySQLビュー定義について
参考:ALTER VIEW構文、CREATE VIEW構文より抜粋
If you specify the DEFINER clause, these rules determine the legal DEFINER user values:
DEFINER句が指定されている場合、これらの規則によってビュー定義者の値が決定されます.
  • If you do not have the SUPER privilege, the only legal user value is your own account, either specified literally or by using CURRENT_USER. You cannot set the definer to some other account.
  • もしあなたのアカウントにsuper権限がなければ、唯一指定できる合法的なユーザーはあなた自身であり、CURRENT_を指定してもUSERはフルネームです.
  • If you have the SUPER privilege, you can specify any syntactically legal account name. If the account does not actually exist, a warning is generated.
  • super権限がある場合は、DEFINERとして任意のユーザーを指定できます.ユーザーが存在しない場合は、警告が表示されます.
  • Although it is possible to create a view with a nonexistent DEFINER account, an error occurs when the view is referenced if the SQL SECURITY value is DEFINER but the definer account does not exist.
  • エラーのユーザーを定義者として指定できますが、SQLセキュリティ検出がDEFINERレベルに設定されているときにビューを参照するとエラーが表示されます.

  • 3.クロスライブラリビューの権限およびSQL SECURITYについて
    ビューのSQLセキュリティ検出メカニズムについて説明したが、3つ目は、存在しないビュー定義者を指定した場合、ビューがエラーを実行する可能性があるという例を参照してください.
    -- login as root
    GRANT SELECT ON hive.* TO 'test'@'%' IDENTIFIED BY '123';
    USE HIVE
    CREATE VIEW v AS SELECT * FROM hue.auth_group;
    SHOW CREATE VIEW v\G
    -- Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v` AS select `hue`.`auth_group`.`id` AS `id`,`hue`.`auth_group`.`name` AS `name` from `hue`.`auth_group`
    ALTER DEFINER=t@'%' VIEW v AS SELECT * FROM hue.auth_group;
    -- user t not exist
    SHOW WARNINGS;
    -- +-------+------+----------------------------------------------------------+
    -- | Level | Code | Message                                                  |
    -- +-------+------+----------------------------------------------------------+
    -- | Note  | 1449 | The user specified as a definer ('t'@'%') does not exist |
    -- +-------+------+----------------------------------------------------------+
    ALTER DEFINER=t@'%' SQL SECURITY DEFINER VIEW v AS SELECT * FROM hue.auth_group;
    SELECT * FROM v;
    -- ERROR 1449 (HY000): The user specified as a definer ('t'@'%') does not exist
    ALTER DEFINER=t@'%' SQL SECURITY INVOKER VIEW v AS SELECT * FROM hue.auth_group;
    -- ok
    ALTER DEFINER=test@'%' VIEW v AS SELECT * FROM hue.auth_group;
    -- ERROR 1356 (HY000): View 'hive.v' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
    ALTER DEFINER=test@'%' SQL SECURITY DEFINER VIEW v AS SELECT * FROM hue.auth_group;
    -- error still
    ALTER DEFINER=test@'%' SQL SECURITY INVOKER VIEW v AS SELECT * FROM hue.auth_group;
    -- fine

    上の栗の真ん中はどうして間違えたのですか.SQL Securityを指定すると、文の実行にどのような影響がありますか?そして、なぜ追加の安全検出メカニズムを制定するのでしょうか.
    参照mysqlストアド・プロシージャ権限については、Access Control for Stored Programs and Viewsから抜粋します.
    DEFINERとSQL SECURITYは標準SQLの拡張です.標準SQLで定義されたビューの定義者は、ビューの文所有者です.
    ただし、MySQLでは「文所有者」という言い方はありませんので、ビューの実行検出を制御する権限を追加定義する必要があります.
    実際にビューの定義者は、デフォルトでビューを作成する人です.MySQL 5.0.16以前のバージョンでは、この2つのプロパティは無効です.次の内容は、公式ドキュメントから翻訳されています.
    Definer and invoker security contexts differ as follows:
    Definerとinvokerの両方の安全環境検出の違いは以下の通りである.
  • A stored program or view that executes in definer security context executes with the privileges of the account named by its DEFINER attribute.
  • ストアド・プロシージャ(またはビュー)がdefinerセキュリティ・コンテキストで実行するために必要な権限は、rootがdefinerセキュリティ・モードを定義したライブラリ間ビューなど、定義者属性が指定したユーザー権限にのみ関連します.他のユーザーがライブラリ間権限を持っていなくても、ビューを正しく実行できます.
  • A stored routine or view that executes in invoker security context can perform only operations for which the invoker has privileges. The DEFINER attribute can be specified but has no effect for objects that execute in invoker context.
  • プロシージャまたはビューがinvokerモードで実行されると、ストアド・プロシージャ内の文(またはビュー定義)の実行権限が検出されます(たとえば、ライブラリ間ビューでは、現在の実行ユーザーが対応するライブラリの対応する権限を持っているかどうかを検出します).ビュー定義者というプロパティは有効になりません.

  • 簡単に言えば(MySQLのビュー(1)ビューのセキュリティ検証を全面的に学習した方法から参照):
    definerは、オブジェクトの定義に権限があるかどうかを判断し、作成したユーザーに権限があれば作成に成功し、ビューをクエリーする権限のあるすべてのユーザーがクエリー文を正常に実行できます.ビューが参照するオブジェクトの権限があるかどうかにかかわらず
    invokerとは、クエリー時にユーザーが操作を実行する権限があるかどうかを検証することであり、もちろん作成時にも、作成したユーザーが参照テーブルオブジェクトを表示するアクセス権限がない場合、作成は失敗すると判断します.
    4.MySQLのdatetimeとtimestampの比較
    MySQLのtimestampはdatetimeタイプに比べてバイト数が小さいことはよく知られていますが、時間範囲は一時的に制限されています.
    それだけでなく、1つのテーブルで最大1つのタイムスタンプを自動的に更新するtimestampフィールドもサポートされています.
    MySQLでは現在、関数をデフォルト値としてサポートしていないため、datetimeでは実現できません.しかし、時間がタイムゾーンの影響を受けるという大きな弊害があります.
    同様に、JavaプログラムのDateクラスとそのサブクラスもタイムゾーンの影響を受けます.栗をもう一つ見てみましょう.
    public static void main(String[] args) throws Exception {
    	Date d = new Date();
    	System.out.println(d);
    	String file = "c:/crs.oos";
    	TimeZone timezone = TimeZone.getDefault();
    	//             
    	ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
    	oos.writeObject(d);
    	oos.flush();
    	oos.close();
    	//   JDK      
    	timezone.setRawOffset(-36000000);
    	TimeZone.setDefault(timezone);
    	//              
    	ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
    	Date d1 = (Date) ois.readObject();
    	ois.close();
    	System.out.println(d1);
    }

    上記のプログラムを実行すると、時間が変わったことがわかります(シーケンス化の目的は、以前の時間が一定であることをよりイメージ的に示すことです).
    なぜファイルを書き込む時間が再び読み込まれて変わったのでしょうか?
    実はJavaのDateの実装はMySQLのtimestampの実装と似ています.解決策も大同小異:
    --   unixtimestamp   ,     datetime
    SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(NOW()));
    --        
    SELECT CAST(NOW() AS CHAR(20));

    文字列に変換した後、追加の処理は必要ありません.Dateタイプに戻せばいいです.直接転送されたDateクラスであれば、タイムゾーン変換が必要です.
    // timezone              
    public static Object getObject(int index, int timezone, CachedRowSet crs) throws Exception {
    	int type = crs.getMetaData().getColumnType(index)
    	if (java.sql.Types.DATE == type)
    		return crs.getDate(index);
    	else if (Types.TIME == type)//       
    		return crs.getTime(index, Calendar.getInstance(TimeZone.getTimeZone("GMT+" + (8 + timezone))));
    	else if (Types.TIMESTAMP == type) {
    		if (timezone == 0)
    			return crs.getTimestamp(index);
    		Timestamp times = crs.getTimestamp(index, Calendar.getInstance(TimeZone.getTimeZone("GMT+" + (8 + timezone))));
    		times.setNanos(0);
    		return times;
    	} else if (Types.CHAR == type || Types.VARCHAR == type || Types.NCHAR == type || Types.NVARCHAR == type) {
    		return crs.getString(index);
    	} else
    		return crs.getObject(index);
    }

    参考:Java TimeZone
    5.other tips
    MySQLフィールドの改行とリターンバーを削除するには、次の手順に従います.
    UPDATE tb SET field=REPLACE(REPLACE(field,CHAR(10),''),CHAR(13),'')

    char(10):  改行;char(13):  折り返し記号TRIM():スペースの除去
    mysqlテーブルの複数列交差重量除去問題
    MySQLソートルール:MySQLにも潜在的なルールがあります.Select文にOrder Byを付けないでどのようにソートしますか.MySQLデフォルトのソートを変更するには:
    ALTER TABLE tb ORDER BY field DESC
    

    MySQL int(11)とint(3)の違いは、zerofillを付けてこそ表示長の違いがあり、実際には4バイトを占有しています.